Author Topic: calculating variable issue  (Read 2126 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
calculating variable issue
« on: August 21, 2018, 01:24:39 pm »
I need to do something like:

uint16_t speed_2_digital = (uint16_t)(1000000U/(((SPEED_2_RPM*3)/60)));

SPEED_2_RPM = 47'000.

I do not get the desired result with or without the type casting. Am I exceeding some limit? I get the same result be it a variable or using a macro and regardless of the typecast, or do I need to typecast it high in order to do the math that then goes into a 16 bit variable?
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #1 on: August 21, 2018, 01:25:42 pm »
20'000 works but produces a round 1000, 47'000 does not but it is not a rannd number
 

Offline dmills

  • Super Contributor
  • ***
  • Posts: 2093
  • Country: gb
Re: calculating variable issue
« Reply #2 on: August 21, 2018, 01:51:31 pm »
47000 * 3 = 141000, what is INT_MAX (from <limits.h> on your platform?).

What type is SPEED_2_RPM? 
I would note that (((SPEED_2_RPM*3)/60)) is pretty much equivalent to (SPEED_2_RPM / 20) reducing the integer range required.

Also that 1000000 can be multiplied by the 20 to give you
uint16_t speed_2_digital = 20000000UL/SPEED_2_RPM;

Regards, Dan.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3241
  • Country: gb
Re: calculating variable issue
« Reply #3 on: August 21, 2018, 01:56:47 pm »
I need to do something like:

uint16_t speed_2_digital = (uint16_t)(1000000U/(((SPEED_2_RPM*3)/60)));

SPEED_2_RPM = 47'000.

Not enough information, is SPEED_2_RPM a #defined literal?  If so you need to show this.

Assuming :

1) #define SPEED_2_RPM 47000
2) You are using a platform with 16 bit integers

Then (SPEED_2_RPM*3) will immediately overflow a 16 bit integer.  To fix this you need to tell the compiler you want to treat the literal (or the multiplier) as a 32 bit value e.g.

#define SPEED_2_RPM 47000UL


 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #4 on: August 21, 2018, 05:04:46 pm »
If it is still AVR, then int is 16-bits and you need to watch out for integer overflows.

Something like this should work better: "uint16_t speed_2_digital = (uint16_t)(1000000U/((((uint32_t)SPEED_2_RPM*3)/60)));"

Although depending on what you are doing, you ma be better off rearranging things in this formula (specifically turn /60 to *60 in the numerator).
« Last Edit: August 21, 2018, 05:08:35 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #5 on: August 21, 2018, 05:27:40 pm »


Something like this should work better: "uint16_t speed_2_digital = (uint16_t)(1000000U/((((uint32_t)SPEED_2_RPM*3)/60)));"



Nope.

I was originally trying to do this as a macro but wondered if i needed to forcibly typecast it in a variable assignment. So I simply need to define a number as UL to break out of the 16 bit limit. Yes the speed was going to be a #define.

I carried out multiplications first to try and avoid too much discard in dividing.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #6 on: August 21, 2018, 05:38:06 pm »
What is the actual result you get. Because for 20000, the correct result is 1000. So I'm not sure why you have "but" in the second post.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #7 on: August 21, 2018, 05:42:36 pm »
20'000 works, 47'000 does not. 1000 is a round number, the result of 47000 is 425.something so the .something needs discarding.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #8 on: August 21, 2018, 05:44:01 pm »
the result of 47000 is 425.something so the .something needs discarding.
Yes, but what value do you actually get when comping the code?
Alex
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11693
  • Country: my
  • reassessing directives...
Re: calculating variable issue
« Reply #9 on: August 21, 2018, 05:53:55 pm »
If it is still AVR, then int is 16-bits and you need to watch out for integer overflows.
a good compiler will know how to promote to 32 bit integer operation but i've not seen automatic promotion to floating point operation...

the result of 47000 is 425.something so the .something needs discarding.
Yes, but what value do you actually get when comping the code?
the value is 425.53191489361702127659574468085 he should get 425 or 426 depending on compiler. he got round off error nevermind...
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #10 on: August 21, 2018, 05:55:48 pm »
a good compiler will know how to promote to 32 bit integer operation but no way i've seen promoted to floating point operation...
Not really. Compiler promotes things to 'int' regardless of its size. The problem is that on AVR int is 16 bits.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #11 on: August 21, 2018, 06:04:22 pm »
Well i tried making the variable a float.... nothing. I can of course use UL for the macro values.
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11693
  • Country: my
  • reassessing directives...
Re: calculating variable issue
« Reply #12 on: August 21, 2018, 06:10:42 pm »
a good compiler will know how to promote to 32 bit integer operation but no way i've seen promoted to floating point operation...
Not really. Compiler promotes things to 'int' regardless of its size. The problem is that on AVR int is 16 bits.
since he stated he got 425, so its round off error. if its overflow problem, he should get something nonsense like 6060. anyway, either RO or OF, it will be either RO or OF problem ;D
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #13 on: August 21, 2018, 06:10:59 pm »
You need to figure out where the actual evaluation happens. C preprocessor does not do floats, so if the expression is evaluated by the preprocessor, the result will be integer. But with casts all over the place, the compiler will do evaluation. But if all things going in are integers, then the result is going to be integer as well. You need to explicitly cast things to floats.

Alex
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #14 on: August 21, 2018, 06:12:00 pm »
since he stated he got 425, so its round off error.
The way I read it, he wants to get 425, but getting something else. What exactly - I have no clue.
Alex
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11693
  • Country: my
  • reassessing directives...
Re: calculating variable issue
« Reply #15 on: August 21, 2018, 06:17:37 pm »
since he stated he got 425, so its round off error.
The way I read it, he wants to get 425, but getting something else. What exactly - I have no clue.
he answered you twice... we should ask him again if 19000 works.
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #16 on: August 21, 2018, 06:20:54 pm »
You need to figure out where the actual evaluation happens. C preprocessor does not do floats, so if the expression is evaluated by the preprocessor, the result will be integer. But with casts all over the place, the compiler will do evaluation. But if all things going in are integers, then the result is going to be integer as well. You need to explicitly cast things to floats.



well i tried casting the variable calculation as float although variable is 16 bit. I have no idea what the value is. judging by how the system behaves much larger than it should be so I guess an overflow?

Is there a way of finding out what atmel studio is calculating it to? It can be done as a macro or as a variable it does not matter as it is a constant. I just want to be able to set the speed in RPM instead of keep working out the period counts for that RPM's frequency.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #17 on: August 21, 2018, 06:21:18 pm »
since he stated he got 425, so its round off error.
The way I read it, he wants to get 425, but getting something else. What exactly - I have no clue.
he answered you twice... we should ask him again if 19000 works.

No idea, can tell you tomorrow.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17826
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: calculating variable issue
« Reply #18 on: August 21, 2018, 06:24:46 pm »
I suppose it is that.
20'000*3 < 2^16.
47'000*3 > 2^16
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: calculating variable issue
« Reply #19 on: August 21, 2018, 09:19:16 pm »
You need to figure out where the actual evaluation happens. C preprocessor does not do floats, so if the expression is evaluated by the preprocessor, the result will be integer. But with casts all over the place, the compiler will do evaluation. But if all things going in are integers, then the result is going to be integer as well. You need to explicitly cast things to floats.

As far as I knew the C processor does't do math at all, but trusting Ataradov's track record....

Code: [Select]
$ cat pptest.c
#include <stdio.h>

#define A (2)
#define B (1+1)

int main(int argc, char *argv[]) {
#if A == B
  printf("Equal\n");
#else
  printf("Not equal\n");
#endif
}
$ gcc -o pptest pptest.c
$ ./pptest
Equal
$

Oh, that IS interesting! So "(2) == (1+1)" and I checked that "(2) == (1+1+1)" is false.

Suddenly a rabbit hole appears...

Code: [Select]
#include <stdio.h>

#define A (Y)
#define B (N)

int main(int argc, char *argv[]) {
#if A == B
  printf("Equal\n");
#else
  printf("Not equal\n");
#endif
}
$gcc -o pptest pptest.c
$ ./pptest
Equal

WFT - how can "(Y) == (N)" ???? - Let me guess, as 'Y' is undefined it is 0, and so is 'N'.

Must look away before I start reading the C standards...
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11278
  • Country: us
    • Personal site
Re: calculating variable issue
« Reply #20 on: August 21, 2018, 10:01:42 pm »
Yep.

Although in this case preprocessor would not do any evaluation, if it is a simple define that is later used in the code (define as a simple substitution).

The only way preprocessor will get to the evaluation if this define is later used in another preprocessor expression. And casts there will result in direct errors.
Alex
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf