Go Down

Topic: Addition overflow (Read 2160 times) previous topic - next topic

Oct 30, 2012, 03:46 am Last Edit: Oct 30, 2012, 04:53 am by leonelpepe Reason: 1
Hi,

I have a doubt whit the addition instruction and know if an overflow happened.

uint8_t a = 200;
uint8_t b = 200;

uint8_t c = a + b; // the sum is overflowed

// c is 200 + 200 = 400 >>> 400 - 255 = 145

I can tell if the sum is overflowed.

In ASM normally I have the carry bit to know that. In C and in Arduino, can I use a instruction, flag or something similar?

Thanks.

PeterH


In C and in Arduino, can I use a instruction, flag or something similar?


No, there's nothing like that.
I only provide help via the forum - please do not contact me for private consultancy.

OK, it is a very bad news. The only way that I can tinks is that c must be greather than a and b at the same time:

Code: [Select]


uint8_t a = 200;
uint8_t b = 200;

uint8_t c = a + b; // the sum is overloaded

// c is 200 + 200 = 400 >>> 400 - 255 = 145

if (c < a && c < b) {
  // Overload have being success.
}

lloyddean

I think you're referring to 'overflow' not overload.


I think you're referring to 'overflow' not overload.



mmm. Yes, I'm not speak English very well. Sorry.

Coding Badly


Give this a try...

Code: [Select]

bool SafeAdd( uint8_t a, uint8_t b, uint8_t & r )
{
  uint16_t t;
 
  t = a + b;
 
  r = t;
 
  return( (t & 0xFF00) == 0 );
}

bool SafeAdd( uint16_t a, uint16_t b, uint16_t & r )
{
  uint32_t t;
 
  t = a + b;
 
  r = t;
 
  return( (t & 0xFFFF0000) == 0 );
}

void Test1( void )
{
  uint8_t a = 200;
  uint8_t b = 200;
  uint8_t r;

  if ( SafeAdd( a, b, r ) )
  {
    Serial.println( F( "No problem." ) );
  }
  else
  {
    Serial.println( F( "Bad news!" ) );
  }
}

void Test2( void )
{
  uint8_t a = 200;
  uint16_t b = 200;
  uint16_t r;

  if ( SafeAdd( a, b, r ) )
  {
    Serial.println( F( "No problem." ) );
  }
  else
  {
    Serial.println( F( "Bad news!" ) );
  }
}

void setup( void )
{
  Serial.begin( 250000 );
 
  Test1();
  Test2();
}

void loop( void )
{
}



Give this a try...



It is a great idea. Thanks, but... if I want to use a 32 bit variable? jaja

Coding Badly


Then you use uint64_t for the result.

Mitxel

I think, but am not sure, you can access the microcontroller "status register" from C code.

I think in "Arduino C" there is a special variable called "SREG" which is a representation of the status register of the microcontroller. The microcontroller status register contains a collection of flags and one of those flags is the carry flag. I think the carry flag is the flag in the status register bit0 .

You could try something like this:

Code: [Select]
boolean isCarryOverflow()
{
return(SREG & 0x01); //Assuming the carry flag in on bit0
}

void setup()
{
...
...
c = a + b;
if(isCarryOverflow)
{
...
}
...
}


ATmega datasheet >> http://www.atmel.com/Images/doc8161.pdf (page 10)
http://www.wvshare.com/article/AVR-1-1-5.htm

You can download the datasheet of your Arduino microcontroller from arduino.cc >> Products

pYro_65

Quote

• Bit 0 - C: Carry Flag
The Carry Flag C indicates a carry in an arithmetic or logic operation. See the "Instruction Set
Description" for detailed information.


Yeah its bit 0, there is also an instruction 'BSET' for checking bits in the status register.

Krupski


Hi,

I have a doubt whit the addition instruction and know if an overflow happened.

uint8_t a = 200;
uint8_t b = 200;

uint8_t c = a + b; // the sum is overflowed


An unsigned 8 bit INT can only hold a value from 0 to 255 (decimal). If you add one to 255, it "rolls over" back to zero.

You need to use a larger INT... maybe a uint16_t (16 bits - 0 to 65535) or a uint32_t (32 bits - 0 to 4294967295) or even a uint64_t (64 bits.... ginormous!)

You can detect if a variable has overflowed. There is no carry bit available to C, but if the result is smaller than you expect, you can assume that an overflow has occurred.

Note that this is also true with subtraction... a uint8_t with a value of 0, minus 1 = 255. In this case, the result is larger than you expect and this signifies a borrow.
Gentlemen may prefer Blondes, but Real Men prefer Redheads!

Coding Badly

#11
Nov 07, 2012, 07:07 pm Last Edit: Nov 07, 2012, 07:10 pm by Coding Badly Reason: 1
I think, but am not sure, you can access the microcontroller "status register" from C code.


You can but doing so is "dangerous".  The compiler can reorder (or even remove) code when it optimizes.  When you write this...

Quote
[font=Courier New]c = a + b;
if(isCarryOverflow())
{
...
}
// Some code after the if that has no dependency on anything above.[/font]


The compiler could do something like this...

Quote
[font=Courier New]c = a + b;
// Some code that was after the if that has no dependency on anything nearby.
if(isCarryOverflow())
{
...
}[/font]


In other words, there is no way to guarantee the SREG check is performed immediately after the addition.

Mitxel

You can but doing so is "dangerous".  The compiler can reorder (or even remove) code when it optimizes.  When you write this...


Yes, the compiler optimizer is always surprising.

This guy (http://www.fefe.de/intof.html) says that if an addtion  of integers owerflowed, then the sum is always less than either addend. (I do not know the reason)

Then, say, we have A which is an integer of 48 bits, consisting A_Hi (16 bits) and A_Low (32 bits) and we add B which is a 32-bit integer.

Maybe something like that would work

Code: [Select]

unsigned int A_Hi;
unsigned long A_Low;
unsigned long B;

A_Low += B;
if(B > A_Low) A_Hi ++;


(I apologize for my horrid English)

PeterH


This guy (http://www.fefe.de/intof.html) says that if an addtion  of integers owerflowed, then the sum is always less than either addend. (I do not know the reason)


I haven't followed that link, but I expect you meant to say that at least one of the addends will be greater than the sum (they may not both be greater).
I only provide help via the forum - please do not contact me for private consultancy.

robtillaart

Quote
I haven't followed that link, but I expect you meant to say that at least one of the addends will be greater than the sum (they may not both be greater).


if a <=255 and b<=255 and a+b > 255 ==>  (a+b)%256 < a  and (a+b)%256 < b

you can test this quite simple
Code: [Select]

void setup()
{
  Serial.begin(115200);
  for (uint8_t a = 0; a < 255; a++) // 255 not in the loop to prevent endless loop
    for (uint8_t b = 0; b < 255; b++)
    {
      uint8_t c = a + b;
      uint16_t d = (uint16_t )a + b;
      Serial.print((int)a);
      Serial.print('\t');
      Serial.print((int)b);
      Serial.print('\t');
      Serial.print((int)c);
      Serial.print('\t');
      Serial.print(c < a?"overflow":"ok");
      Serial.println();
    }
}
void loop(){}


but you can test overflow before it occurs just by doing a subtraction, no need to test a register, works for 16, 32 and 64 bit

Code: [Select]

void setup()
{
  Serial.begin(115200);
  for (uint8_t a = 0; a < 255; a++)
    for (uint8_t b = 0; b < 255; b++)
    {
      if (255 - b < a ) Serial.println("overflow");
      else Serial.println((int)(a+b));
    }
}
void loop(){}



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up