The Java Language Specification point 3.10.2 states that floating point values are converted as specified in the IEEE 754 standard. For strtod
, the C standard specifies how the function converts text to float values. Regarding the representation itself, the two seem to cover identical cases. What I'm not sure about is, how is it with the rounding rules? Does the Java compiler do a different conversion than what strtod
does?
Background is that I want to compile to Java bytecode code and therefore need to convert textual representations of float/double values for the representation in the class file.
For example, this Java code prints a more exact value:
double value = 1.23412991913372577889911;
System.out.println(value);
// Output: 1.2341299191337258
Converting the same value using strtod and printing it out prints a less exact value:
const char* textual = "1.23412991913372577889911";
double result = strtod(textual, ...);
std::cout << result << std::endl;
// Output: 1.23413
Is this an output issue, or is the value actually converted in a different way?
EDIT: as Pascal Cuoq commented, when printing out the value with full precision (I did so by settings std::cout.precision()
), the values are equal, so I assume the conversion leads to the same values. I guess I'll do a test for that. :-)
Yes, there are differences. Here are two that I could find.
Java supports underscores between digits. From the spec:
Underscores are allowed as separators between digits that denote the whole-number part, and between digits that denote the fraction part, and between digits that denote the exponent.
This shouldn't be a problem in your case. You only have to strip all underscores.
Java mandates the round-to-nearest rule of IEEE 754 floating-point arithmetic. From the Java spec (the language spec refers to Double.valueOf
):
[This] exact numerical value is then conceptually converted to an "infinitely precise" binary value that is then rounded to type double by the usual round-to-nearest rule of IEEE 754 floating-point arithmetic, which includes preserving the sign of a zero value.
The rounding mode of strtod
is implementation-defined and IIUC it even allows an error of 1 ULP. From the C99 spec (the strtod
documentation refers to section 6.4.4.2):
For decimal floating constants, and also for hexadecimal floating constants when FLT_RADIX is not a power of 2, the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner.
Only if your C compiler supports Annex F: IEC 60559 floating-point arithmetic, strtod
is guaranteed to conform to IEEE 754 (IEC 60559 and IEEE 754 are equivalent):
The translation time conversion of floating constants and the strtod, strtof, strtold, fprintf, fscanf, and related library functions in <stdlib.h>, <stdio.h>, and <wchar.h> provide IEC 60559 binary-decimal conversions.
Also note that strtod
supports hexadecimal floating point notation only since C99 (Java since version 5). So check how your implementation of strtod
behaves.