0

It's possibly a very stupid question, but I've been searching for a whole day and I couldn't get an answer...

Let's say I have a double-precision floating point literal: 5.21. Calling Double.toString( 5.21 ) in Java yields the string "5.21".

Now, let's say we have Java, but without toString and valueOf, nor can I format it with String.format or just by concatenation. How would I be able to convert my number to a string, assuming that I only have the binary representation?

More specifically, how do Double.toString and dtoa exactly work: how can I write my own toString/dtoa function (assuming we're dealing with IEEE 754 double-precision floating points)?

Samū
  • 488
  • 3
  • 15

2 Answers2

4

This is a surprisingly tricky problem, especially to do it efficiently and accurately. There are two main concerns:

  1. Each binary-float represents a set of "real" numbers centered around it, and the size of this interval depends on the value itself. (In general, the larger the value, the larger the interval it represents.) A "correct" conversion is usually defined as picking an element in this set, which will contain many decimal floats.

  2. Of the "correct" choices, one usually wants the "optimal" output, i.e., the string with the least number of decimal digits.

So, as with anything floating point, the rabbit-hole goes deep even for innocuous-sounding questions like this. A good algorithm is both correct and optimal in the above sense; which makes it tricky to design one that is also efficient.

But you're in luck. It's also a very well studied problem:

It’s amazing that the first and the last paper above are 20 years apart, attesting to the difficulty of the problem. If you come up with a better technique, it’d definitely be a publishable result. Enjoy!

alias
  • 28,120
  • 2
  • 23
  • 40
  • 1
    "*not every binary-float as described in IEEE-754 has a finite decimal representation*" - I can't think of how that would be: successive powers of two (positive or negative) always have finite decimal representations (even [epsilon](https://learn.microsoft.com/en-us/dotnet/api/system.double.epsilon) is [finite](https://www.wolframalpha.com/input/?i=2%5E-1074)) so I can't see how combinations of them would not. (maybe I've missed something) – Wai Ha Lee Dec 02 '19 at 07:36
  • 1
    @WaiHaLee Good point. I should've said it the other way around: Not every decimal float can be represented accurately in binary floating-point. (`0.1` being the canonical example.) Though of course this isn't what the OP was asking. Edited to clarify and also added another reference. – alias Dec 02 '19 at 08:25
0

how can I write my own toString/dtoa function (?)

Every finite binary based floating point number has an exact decimal representation. Consider each such floating point number is the sum of various powers of 2 and each power of 2 itself is exact in decimal: e.g.: 256, 2, 0.25, 0.0625.

Function to print a double - exactly converts by carefully extracting the floating point's significand as a whole number and exponent. Then it is a simply case of looping and *2 or /2 as needed. This provides an exact answer.

Often a rounded result is acceptable. That becomes more complicated, yet speedier.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • This would do something but I don't think this is the best and most optimal solution to the problem... – Samū Dec 05 '19 at 20:59
  • @RgSW It depends on the coding goal. Do you want an exact conversion or an approximate one? Many a case will suffice with an approximate, some not. – chux - Reinstate Monica Dec 06 '19 at 02:37