Integer overflow problem when it is within range?

Hello. I am trying to understand why the variable H is overflowing. It is of type float which according to the guide can take very large numbers:

Floating-point numbers can be as large as 3.4028235E+38 and as low as -3.4028235E+38. They are stored as 32 bits (4 bytes) of information.

In the code below, the function func() simply takes in a number between 0 and 255, squares it and stores it into the float variable. The maximum number upto which I get the correct result is 181.

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

void loop() {
  func(181); // prints correct answer: 32761.00
  func(182); // prints wrong answer: -32412.00
  delay(1000);
  exit(0);
}

void func(byte x) { /* I replaced byte with int but problem persists*/ 
  float H;
  H = x*x;
  Serial.println(H);
}

I chose byte because in the actual function I wish to write 0-255 is all the range I need. But for experimenting, I tried replacing the type byte with int. 182 * 182 = 33,124 is well within the range for a 32 bit integer right? but the problem still persists. Any help is appreciated. Thanks!

If you have an 8 bit Arduino, the expression x*x overflows the default 16 bit signed integer calculation.

Even if the default int is 32 bits, I vaguely recall that "byte" is promoted to 16 bits.

It does not matter that H is declared float.

Make x an unsigned int

By the way, what do you imagine that exit(0); is doing as there is no OS to exit to on an Arduino

And you can force float output:

H = (float) x*x;

image

Thanks. One of the posts below suggested type casting the result to (float) while another suggested using unsigned int. What would be the most economical in terms of memory usage? Just curious.

Thanks, I've always used exit() because it stopped the loop. Is there anything better for doing that?

Me too :wink: so I await the answer as well.

while(1);

Is a common method.

1 Like

If you only want stuff to go once, put it in setup().

1 Like

Your variables are dynamic because they are in a function. So they use no permanent memory. Use whatever data types are safe, and make sense for your application.

1 Like

Why does that matter?

1 Like

Anything smaller than int is promoted to int.

Or put the code in setup()

1 Like

@20nik00

1. Computer is not a natural thing like a tree; rather, it is an artificial entity created by human being and has rained it to follow some rules. So, the user needs to take care that he puts the rules correctly.

2. You have passed 181/182 (0xB5/0xB6), which has been accepted by the called program as an unsigned value. It is a positive value and you will multiply it by itself; as a result, the product/result will be a positive number. You know this rule? Does computer know it?. So in the called function, you have to do the following computation:

uint16_t y = x*x;

3. Now to save the result (y) into a float-type variable H, you have to float-cast y to add the fractional part (0.0).

float H = (float)y;

4. Final Sketch would appear as:

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

void loop() 
{
  func(181); // prints correct answer: 32761.00
  func(182); // prints wrong answer: -32412.00
  delay(1000);
  exit(0);
}

void func(byte x) 
{ 
  uint16_t y = x*x;
  float H;
  H = (float)x * x;
  Serial.println(H); //shws: 32761.00, 33124.00
}

Is the MCU stopped or crashed -- because, there is no OS (post #3) to make a return?

What will happen if your enable INT0-interrupt without declaring/defining the corresponding ISR in the sketch? This situation can be easily created in ASM/Machine Programming and not in Arduino.

Thanks. I'll keep that in mind. I had some idea that exit() returned value to the OS in a traditional PC running an OS and for some reason thought that Arduino's C++ implementation of exit() did something equivalent for the AVR MCU. There are better solutions proposed by others in this thread. I wont be using exit() again.

Well my embedded systems classes always told me that memory is at a premium in micro-controllers, like with the Uno which I am using that has 32KB. Admittedly this is not an issue in this particular instance.

depends, if you have 8 bit MCU you have 16 bit int

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.