Calculation always returns 0

I tried to calculate the value of ThisRampTime in an if statement (without declaring it as variable, just the calculation) for doing a delay with millis(). But it always returned 0 and my if statement was executed instantly.

Then I assumed maybe it overflows some variable in the If function and calculated it outside of the if statement. It also returned 0.

Then I assumed it migh be possible float is needed so I changed the int declaration to float But it still returns 0! Even with brackets around the calculation....

WHY? Float should be big enough as far as I looked up.

int RampTime = 5000;
int RampPWM = 64;
float ThisRampTime = 0;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  ThisRampTime = ((RampTime * RampPWM) / 65280000);
  Serial.println((float)ThisRampTime);
}

What is the result of 5000 * 64? Think it might fit in an int?

integer math.

define your dividend and divisor as floats or cast them to floats

But do know you loose accuracy in the esteems of a float (very large or very small).

... and don't forget to show the digits:

  Serial.println(ThisRampTime, 8);

I tried int in the beginning and it did'nt work therefore I started using float.

I tried to calculate the time for :

  if (millis() - Ramp_Timer >= (RampTime / 65280000 * RampPWM) )
  {
    RampPWM = RampPWM - 1;
  }

Okay, so where does that leave you? Please explain this magic number 65280000. What are you trying to do?

And you should notate it 65280000L if its a long constant, 6.528e7 if its a float constant.
The default int type is 16 bit which is not able to represent the number 65280000

Format the number as long. I had a problem where I was dividing by a large number and I suppose I didn't have enough resolution

No need to. Can't find if it's default C behavior but the avr-gcc compiler is smart enough to see that it doesn't fit an int.

@johnvorsten, can you show us?

This was what I tried after calculating it directly in the if statement failed:
It also returns 0!

int RampTime = 5000;
int RampPWM = 64;
unsigned long ThisRampTime = 0;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  ThisRampTime = RampTime * RampPWM / 65280000;
  Serial.println(ThisRampTime);
}

I wanted to calculate the time that needs to pass before the if statement will be executed next time with the same speed.

I probably have messed my formula up I saw now. But anyhow....

Why do I get always 0 as result?

Gorkde:
Why do I get always 0 as result?

asked and answered, I believe.

in integer math:

6 / 9 = 0

where in floating point math

6 / 9 = 0.66666666

You need to declare constants long if you want the operator to be long:

void setup() 
{
  Serial.begin (115200) ;
  
  int a = 1000 ;
  long b = a * 1000 ;  // wrong
  long c = b / 100000 ;  // wrong
  Serial.println (a) ;
  Serial.println (b) ;
  Serial.println (c) ;
  b = a * 1000L ;   // correct constants, the right * and / operations are used
  c = b / 100000L ;
  Serial.println (b) ;
  Serial.println (c) ;

}

void loop()
{}

Produces output

1000
16960
0
1000000
10

Bulldog: Thats what I thought as well and why I tried using float.

Mark: Thanks, that’s the reason… Never had that problem before…

Thanks mates then I should get it working now!

@MarkT and @Gorkde as well, that's ONLY because you try to do math that will result in something bigger then an int. But no need to do it on the literal itself if it's stored in a long and is bigger then int.

  b = a * 1000L ;   // correct constants, the right * and / operations are used
  c = b / 100000 ;

Works just fine as well.

Same as

long myLong = 123456;
Serial.print(myLong);

Works fine as well, 123456 is not cropped to an int.

Aka, if the literal is bigger then the default int it's already promoted to long. So you only need to explicit promote a literal (or variable for that matter) if it's used in math that has a possible outcome that's bigger then the size of the variables OR literals used in the math. In your example for example, if a was defined a long there was no need to promote the literal.

Or another "trick" is to use the output variable in the math

int a = 1000;
long b = a;
b = b * 1000;

... and don't forget to show the digits:

Yes, be sure to show 8 digits after the decimal place, for a float with 6 or 7 total digits of accuracy (counting any before the decimal place).

septillion:
But do know you loose accuracy in the esteems of a float (very large or very small).

Floats have exactly the same number of significant figures no matter what their magnitude.

Gorkde:
Bulldog: Thats what I thought as well and why I tried using float.

You only declared the variable storing the result as a float. All of the values used to perform the calculation are integers, so it will use integer arithmetic all the way up to the end, then the assignment converts it to a float. If you want to perform floating point math, you need to declare the variables as floats or convert them to floats when you perform the calculation.

ThisRampTime = (((float)RampTime * (float)RampPWM) / 65280000.0);

Jiggy-Ninja:
Floats have exactly the same number of significant figures no matter what their magnitude.

Maybe I should have the word precision. But that's more of a language thing then a knowledge thing. :stuck_out_tongue:

And you only have to use one float in a calculation to make the whole calculation float. So

ThisRampTime = (RampTime * RampPWM) / 65280000.0;

will do.