This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Integer overflow

Hello to everyone.

When I have to calculate the average of two integer numbers, first i have to add them. Sometimes an overflow occurs. One technique maybe to compare the result to one of the numbers, if result is lower, an overflow is recognized.

Is this good style or better use Assembler?

Parents
  • Depends on your goal. Assembler can be fast, but at the expense of code readability and portability.
    In C, you can use different approaches.
    If your compiler supports a 64-bit long long type, you can use it to calculate the sum without the risk of overflow.
    If a 64-bit integer is not an option, you can use all kinds of tricks, like dividing by 2 prior to addition:

    int average(int a, int b)
    {
        return a/2+b/2; /* instead of (a+b)/2 */
    }
    


    This way you will lose 1 bit of precision in the result. If this cannot be tolerated, you can you can adjust the result to restore precision:

    int average(int a, int b)
    {
        return a/2+b/2+((((a+b)/2)<<31)>>31);
    }
    


    I'm not sure about the last bit, you'd have to check the math. But you get the idea. Regards, - mike

Reply
  • Depends on your goal. Assembler can be fast, but at the expense of code readability and portability.
    In C, you can use different approaches.
    If your compiler supports a 64-bit long long type, you can use it to calculate the sum without the risk of overflow.
    If a 64-bit integer is not an option, you can use all kinds of tricks, like dividing by 2 prior to addition:

    int average(int a, int b)
    {
        return a/2+b/2; /* instead of (a+b)/2 */
    }
    


    This way you will lose 1 bit of precision in the result. If this cannot be tolerated, you can you can adjust the result to restore precision:

    int average(int a, int b)
    {
        return a/2+b/2+((((a+b)/2)<<31)>>31);
    }
    


    I'm not sure about the last bit, you'd have to check the math. But you get the idea. Regards, - mike

Children
  • Hello to everyone,
    thanks for reply.
    Here's my Assembler solution, but i'am not sure it will deliver a correct result under all circumstances!

    //*********************************************************************
    // Computing the average of signed/unsigned numbers in ARM Assembler
    //*********************************************************************
    AREA ?C?bla, CODE, READONLY, ALIGN=2
    
    PUBLIC my_average?A
    my_average?A            PROC CODE32
    
            ADDS    R0,R0,R1      ;add and alter condition code
            MOVVS   R0,R0,RRX     ;if sign has moved to C rotate through Carry
            MOVVC   R0,R0,ASR #1  ;if sign not changed do arithmetic shift
            bx      lr            ; return R0
            ENDP
    
            END
    //*********************************************************************
    

  • Here's the corrected version, divided into average for signed / unsigned numbers.

    //*********************************************************************
    // Computing the average of Signed numbers in ARM Assembler
    //*********************************************************************
    AREA ?C?bla, CODE, READONLY, ALIGN=2
    
    PUBLIC          my_signed_average?A
                            my_signed_average?A             PROC CODE32
    
            ADDS    R0,R0,R1                ;add and alter condition code
            MOVVS   R0,R0,RRX               ;if sign has moved to C rotate through Carry
            MOVVC   R0,R0,ASR #1    ;if sign not changed do arithmetic shift
            bx              lr                              ;return R0
            ENDP
    //*********************************************************************
    // Computing the average of Unsigned numbers in ARM Assembler
    //*********************************************************************
    PUBLIC          my_unsigned_average?A
                            my_unsigned_average?A   PROC CODE32
    
            ADDS    R0,R0,R1                ;add and alter condition code
            MOV             R0,R0,RRX               ;rotate through Carry
            bx              lr                              ;return R0
            ENDP
    
            END
    //*********************************************************************