1

According to this answer the EVM by default uses two's complement notation for handling signed integers. However for my application I would like to work with the sign-magnitude representation where the sign can either be 0 or 1 corresponding to + or - respectively and the remaining bits comprise the magnitude. For example, if a int8 variable has a value of +1 it would be represented in binary as 0000_0001 and if it has a value of -1 it would 1000_0001 in sign-magnitude notation.

However since the EVM uses two's complement I first have to convert it into sign-magnitude representation before I can work with it. How exactly would I do this in a gas-efficient manner?

function twos_comp_to_sign_mag(int8) returns(int8);

// 255 in binary is 1111_1111 or -1 in two's complement notation // 129 in binary is 1000_0001 or -1 in sign-magnitude notation twos_comp_to_sign_mag(255) == 129

MShakeG
  • 1,603
  • 6
  • 37

1 Answers1

1

I asked basically the same question on StackOverflow but for python, below is my solidity adaptation using this answer:

// SPDX-License-Identifier: GPL-3.0
contract TwosComplement {
function twos_comp_to_sign_mag(int8 value) external pure returns(int8) {

    int8 mask = 2**7 - 1; // 0111_1111

    if (value < 0) {
        value = -(value & mask);
    }
    return (-1 & value) | (value & mask);        
}

}

where the following holds true:

twos_comp_to_sign_mag(positiveInt) == positiveInt;
// e.g.: twos_comp(0) == 0

twos_comp_to_sign_mag(negativeInt) == -128 - negativeInt; // ex1: twos_comp(-1) == -128 - (-1) = -128 + 1 = -127 // ex2: twos_comp(-127) == -128 - (-127) = -128 + 127 = -1 // ex3: twos_comp(-128) == -128 - (-128) = -128 + 128 = 0

To adjust this for larger integer types is really simple; change the variable types accordingly and update the mask, so for int16 the mask will be 2**15 - 1.

MShakeG
  • 1,603
  • 6
  • 37
  • What does the & do over here? I used to think that they are only for logical AND operations for comparisons and such. – Ishan Sep 24 '23 at 22:49
  • @Ishan & is a bitwise AND, you can read up on it, but in essence it compares each bit in the value to the corresponding bit in the mask and if both are 1 then the value at that bit in the result is 1 else it's 0 – MShakeG Sep 25 '23 at 07:26