[Ethereum] How to correctly multiply signed int with unsigned int and store the result in `uint32`

solidity

I have an int32 val that contains some negative value such as -1. I want to multiply it with a uint32 value and add a larger uint32 value (for which I know the result will be positive) and store in uint32.

I have come up with the following solution:

uint32 result = uint32( uint32(i) * val + 100)

For example: i=-1, val=10, result should be (-1)*(10) + 100 = 90.

[Q] Is this the correct way to do it?

Since I am casting a signed int to an unsigned int as ( uint32(i) ), shouldn't a negative value (-1) get automatically converted into positive (+1) and give a result of (+1)*(10) + 100 = 110?

 pragma solidity ^0.4.6;
 contract NumTest {
    int8 i;

    function NumTest() {
      i = -1;
    }

    function number() constant returns (uint32 num) {
      uint32 val = 3;
      return uint32( uint32(i) * val + 20);
    }
}

Best Answer

Just commenting on this part...

shouldn't a negative value (-1) get automatically converted into positive (+1)

No, because integers are represented as Two's Complement.

See this previous post for a detailed explanation: Math operation between int and uint


Edit to address comment

Casting -1 with uint32(-1) gives you the value 4294967295 (0b11111111111111111111111111111111 or 0xFFFFFFFF). This is the maximum value an unsigned 32-bit integer can take. This is equivalent to a signed integer value of -1 because of the integer being represented in Two's Complement, as mentioned above.

uint32(i) * val respectively gives you two less: 4294967293 (0b11111111111111111111111111111101 or 0xFFFFFFFD).

If we then add 20, we overflow the (unsigned) integer, which gives us 17. So it looks like it's working by adding 20 to -3, but actually it's adding 20 to 4294967293.