Search code examples
androiddartfloating-pointhexdouble

How to convert Hexadecimal to Double in Dart?


By receiving coordinates encoded as hex, how could I convert them into a double value so that I get a true value of those coordinates? I already tried converting from hex to int and then to double, but I couldn't get the correct value. Is there a Dart package that could this?

I tried the double.parse() return Invalid Double Exception

For reference I have the following hex as a String:

4044B84189374BC1

That should return something like this:

41.43949999999996

I tested with those online converters but I couldn't find a way to do this in Dart language


Solution

  • It is a bit wonky but the following seems to do the trick:

    import 'dart:typed_data';
    
    void main() {
      print(convert('4044B84189374BC1')); // 41.43949999999996
    }
    
    double convert(String hexString) =>
        (ByteData(8)..setUint64(0, int.parse(hexString, radix: 16))).getFloat64(0);
    

    The idea is that I assume the hex string are an normal integer. I then take the 64-bit bits from this int and puts into a bytebuffer and then read this buffer as if it contains a double.

    Improved solution based on feedback from lrn

    The previous suggested solution have the flaw to not work when compiled to JavaScript (since integers in JavaScript does not have 64-bit precision). The following fixes this by handling the parsing in 32-bit parts:

    import 'dart:typed_data';
    
    void main() {
      print(convert('4044B84189374BC1')); // 41.43949999999996
    }
    
    double convert(String hexString) {
      String hexStringPadded = hexString.padLeft(16, '0');
    
      return (ByteData(8)
            ..setInt32(0, int.parse(hexStringPadded.substring(0, 8), radix: 16))
            ..setInt32(4, int.parse(hexStringPadded.substring(8, 16), radix: 16)))
          .getFloat64(0);
    }
    

    The "wonkyness" are still strong since both solutions are still very much dependent on how int and double are stored in the memory, which can change depending on the CPU architecture. The answer here is very much designed specifically for the provided example in the question.