views:

91

answers:

5

I know that most programming languages have functions built in for doing that for you, but how do those functions work?

A: 

A simple (but non-generic, naïve and slow way):

  • convert the number to an integer, then divide this value by 10 stepwise to find out its digits in reverse order. Concatenate them together and you have the integer representation.
  • substract the integer from the original number, now multiply by 10 stepwise and find the digits after the decimal point. Concatenate the first string with a point and this second string.

This has a few problems, of course:

  • slow as hell;
  • doesn't work for negative numbers;
  • won't give you exponential notation for very small or large numbers.

All in all, it's an idea, but not a very good one; I suspect there are no programming languages that do this.

ddvlad
I've seen C code which simply casts a double to a long and access the bits directly. (If I remember correctly, it was the famous optimized invsqrt() function from the Quake engine). But the problem is, that you would have to deal with all those border cases (NaN, Inf, etc.) directly and the specification isn't that short to read/implement ;)
tux21b
A: 

As Oded mentioned in a comment, different languages will do this in different ways. As an example, here's how Ruby 1.9 does it (in C). Your best bet, just as a research exercise, will be to look into open-source languages and see how they do it.

David
So Ruby basically calls printf, which is hardly language agnostic.
Andrew Koester
+1  A: 

The javadoc about the Double toString() method is quite comprehensive:

Creates a string representation of the double argument. All characters mentioned below are ASCII characters.

  • If the argument is NaN, the result is the string "NaN".
  • Otherwise, the result is a string that represents the sign and magnitude (absolute value) of the argument. If the sign is negative, the first character of the result is '-' ('-'); if the sign is positive, no sign character appears in the result. As for the magnitude m:
  • If m is infinity, it is represented by the characters "Infinity"; thus, positive infinity produces the result "Infinity" and negative infinity produces the result "-Infinity".
  • If m is zero, it is represented by the characters "0.0"; thus, negative zero produces the result "-0.0" and positive zero produces the result "0.0".
  • If m is greater than or equal to 10^-3 but less than 10^7, then it is represented as the integer part of m, in decimal form with no leading zeroes, followed by '.' (.), followed by one or more decimal digits representing the fractional part of m.
  • If m is less than 10^-3 or not less than 10^7, then it is represented in so-called "computerized scientific notation." Let n be the unique integer such that 10^n<=m<10^(n+1); then let a be the mathematically exact quotient of m and 10^n so that 1<=a<10. The magnitude is then represented as the integer part of a, as a single decimal digit, followed by '.' (.), followed by decimal digits representing the fractional part of a, followed by the letter 'E' (E), followed by a representation of n as a decimal integer, as produced by the method Integer.toString(int).

How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type double. That is, suppose that x is the exact mathematical value represented by the decimal representation produced by this method for a finite nonzero argument d. Then d must be the double value nearest to x; or if two double values are equally close to x, then d must be one of them and the least significant bit of the significand of d must be 0.

Is that enough? Otherwise you might like to look up the implementation too...

tux21b
A: 

This paper by Guy Steele provides details on how to do this correctly. It's much more subtle than you might think.

http://portal.acm.org/citation.cfm?id=93559

Paul Hankin