2

Given an int256 number n, I want to get the sign of n:

  • If n is positive, get 1
  • If n is negative, get -1
  • If n is 0, get 0

I know that I can do:

function foo(int256 x) external {
    if (x > 0) {
        // ...
    } else if (x < 0) {
        // ...
    } else {
        // ...
    }
}

But this introduces three logical branches in my code, which means gas.

Is there a faster approach? Maybe via some sort of bit manipulation?

1

Before showing the code, the idea is to use the Ternary operator.

condition ? value_if_true : value_if_false

Be careful, since in Solidity 0.8 version overflows/underflows cause a revert, so if you are using ^0.8.x you will need to use an unchecked {...} block.

Code before Solidity 0.8.0 release:

function sign(int256 x) external pure returns (int8) {
    return int8(((0 < x) ? 1 : 0) - ((x < 0) ? 1 : 0 ));
}

Code after Solidity 0.8.0 release:

function sign(int256 x) external pure returns (int8) {
    unchecked {
        return int8(((0 < x) ? 1 : 0) - ((x < 0) ? 1 : 0 ));
    }
}
1

I couldn't work out a single-liner that involved shifting everything right to check the sign bit. It'd be relatively straightforward if bool -> int type conversions were allowed, similar to other languages. In which case you could do something like:

int result = (x != 0) | (x >> 255);

But you can't. (Someone else may know otherwise!)

So something a bit dumber might have to do:

  function foo(int256 x) external pure returns (int) {
    int a =  x > 0 ? 1 : 0;
    int b = x < 0 ? 1 : 0;
    return a - b;
  }

Again, the ternaries are because we can't implicitly convert bool -> int. (And ternary operators are effectively introducing branching... so is this any better than the original question?)

You may find the Bit Twiddling Hacks page useful for similar types of stuff :-)

2
  • Perhaps one could speed up your function by wrapping the code in an "unchecked" block. a-b can never {over,under}flow. Apr 1 at 9:49
  • Yep, agreed - alberto had a very good point. Apr 1 at 11:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.