Dart: split an arbitrarily precised number onto a sequence of bytes

0

Assuming I have a declaration like this: final int input = 0xA55AA9D2;, I'd like to get a list of [0xA5, 0x5A, 0xA9, 0xD2]. It is easily achievable in Java by just right shifting the input by 24, 16, 8 and 0 respectively with subsequent cast to byte in order to cut precision to 8-bit value.

But how to do the same with Dart? I can't find sufficient information about numbers encoding (e.g. in Java front 1 means minus, but how is minus encoded here?) and transformations (e.g. how to cut precision) in order to solve this task.

P.S.: I solved this for 32-bit numbers using out.add([value >> 24, (value & 0x00FFFFFF) >> 16, (value & 0x0000FFFF) >> 8, value & 0X000000FF]); but it feels incredibly ugly, I feel that SDK provides more convenient means to split an arbitrarily precised number into bytes

dart
asked on Stack Overflow May 2, 2019 by nyarian • edited May 2, 2019 by nyarian

2 Answers

1

From the documentation to the int class:

The default implementation of int is 64-bit two's complement integers with operations that wrap to that range on overflow.

Note: When compiling to JavaScript, integers are restricted to values that can be represented exactly by double-precision floating point values. The available integer values include all integers between -2^53 and 2^53 ...

(Most modern systems use two's complement for signed integers.)

If you need your Dart code to work portably for both web and for VMs, you can use package:fixnum to use fixed-width 32- or 64-bit integers.

answered on Stack Overflow May 3, 2019 by jamesdlin
1

The biggest issue here is that a Dart int is not the same type on the VM and in a browser. On the native VM, an int is a 64-bit two's complement number. In a browser, when compiled to JavaScript, an int is just a non-fractional double because JavaScript only has doubles as numbers.

If your code is only running on the VM, then getting the bytes is as simple as:

int number;
List<int> bytes = List.generate(8, (n) => (number >> (8 * n)) & 0xFF);

In JavaScript, bitwise operations only work on 32-bit integers, so you could do:

List<int> bytes = List.generate(4, (n) => (number >> (8 * n)) & 0xFF);

and get the byte representation of number.toSigned(32). If you want a number larger than that, I'd probably use BigInt:

var bigNumber = BigInt.from(number).toSigned(64);
var b255 = BigInt.from(255);
List<int> bytes = List.generate(8, (n) => ((bigNumber >> (8 * n)) & b255).toInt());
answered on Stack Overflow May 3, 2019 by lrn

User contributions licensed under CC BY-SA 3.0