0

I'm new to Dart and porting a project from c#. Where int32 bit been used throughout the code.

simple expressions like

(someInt1 * ((someInt2 * someInt3) - someInt4 - (someInt5 * someInt6) - someInt7 )

gives inconsistent results when compared, as in c# code, it gets overrun its size and returns negative value, but that's been handled in the code and that's what i need.

Is there a way I can purposely use 32bit int instead of Dart's 64bit ?

4
  • 2
    Writing code that explicitly depends on integer overflow sounds like an anti-pattern and reeks of code smell. Maybe if you described what you're actually trying to achieve? Commented Sep 23, 2020 at 0:05
  • You can use package:fixnum if you need to work with fixed-width integers. That said, I also do not recommend depending on overflow behavior. As you've observed, it's brittle and non-portable (in some languages, signed integer overflow is undefined behavior). Commented Sep 23, 2020 at 3:12
  • @Abion47 I know, but it's an existing project and can't simply change it now. Commented Sep 23, 2020 at 11:53
  • @AlphaTry You should try to change it anyway. This is broken code. Integer overflow is something that should be prevented, not "handled". This is the equivalent of checking for null or if an index is in an array with a try/catch. There is no aspect of this code that is redeemable, and it should be purged with fire. Don't pass the technological debt along. Pay some of it off. And let's be honest here. How much would it break your C# project to just use long instead? Commented Sep 23, 2020 at 15:20

1 Answer 1

3

Dart does not have a native 32-bit integer type. The int type is a 64-bit two's complement type when run natively, and it's a non-fractional 64-bit floating point type when compiled to JavaScript (because that's what JavaScript has).

The most general solution is to use the Int32 type from the fixnum package. Then somebody else has worried about the problem for you. It's less efficient than just using int operations, but it will maintain consistent 32-bit semantics.

Depending on overflow behavior of the int type is not going to work the same on all platforms. If you only care about native code, and your expression only uses *, - and + like above, you can just call toSigned on the result. That gives you the low 32 bits of the result, which is the same result as using 32-bit numbers for the entire computation:

var result = 
 (someInt1 * ((someInt2 * someInt3) - someInt4 - (someInt5 * someInt6) - someInt7).toSigned(32);

It's not actually using 32-bit numbers, and it doesn't work if you also do division. It will not work the same when compiled to JavaScript because the overflow behavior when an intermediate result is greater than 253 differs.

You can choose to do .toSigned(32) on every intermediate result:

var result = ((someInt1 *
            ((((someInt2 * someInt3).toSigned(32) - someInt4).toSigned(32) -
                        (someInt5 * someInt6).toSigned(32))
                    .toSigned(32))
                .toSigned(32)) -
        someInt7)
    .toSigned(32);

Not particularly readable, and still won't be enough when compiling to JavaScript, because even two 32-bit integers multiplied may lose precision when the result is represented as double.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.