Java编译器的文本到浮点值转换是否与strtod不同?

时间:2015-11-16 12:03:32

标签: java compiler-construction floating-point strtod

Java语言规范point 3.10.2指出浮点值按照IEEE 754标准的规定进行转换。对于strtod,C标准指定函数如何将文本转换为浮点值。关于代表本身,这两个似乎涵盖了相同的案例。我不确定的是,舍入规则如何? Java编译器是否进行了与strtod不同的转换?

背景是我想编译为Java字节码代码,因此需要为类文件中的表示转换float / double值的文本表示。

例如,此Java代码打印更准确的值:

double value = 1.23412991913372577889911;
System.out.println(value);
// Output: 1.2341299191337258

使用strtod转换相同的值并将其打印出打印一个不太准确的值:

const char* textual = "1.23412991913372577889911";
double result = strtod(textual, ...);
std::cout << result << std::endl;
// Output: 1.23413

这是输出问题,还是实际以不同方式转换的值?

编辑:正如Pascal Cuoq评论的那样,当用完全精度打印出值时(我是通过设置std::cout.precision()完成的),值是相等的,所以我假设转换导致相同的价值观。我想我会为此做一个测试。 : - )

1 个答案:

答案 0 :(得分:1)

是的,有差异。这是我能找到的两个。

  1. Java支持数字之间的下划线。来自规范:

      

    允许下划线作为表示整数部分的数字之间的分隔符,以及表示分数部分的数字之间以及表示指数的数字之间的分隔符。

    在您的情况下,这应该不是问题。您只需剥离所有下划线。

  2. Java规定了IEEE 754浮点运算的舍入到最接近的规则。从Java spec(语言规范引用Double.valueOf):

      

    [此]精确数值然后在概念上转换为“无限精确”二进制值,然后通过IEEE 754浮点运算的通常舍入到最接近的规则舍入为double类型,其中包括保留符号零值。

    strtod的舍入模式是实现定义的,IIUC甚至允许1 ULP的错误。从C99规范(strtod文档参考6.4.4.2节):

      

    对于十进制浮点常量,以及当FLT_RADIX不是2的幂时,对于十六进制浮点常量,结果是最接近的可表示值,或紧邻最近可表示值的较大或较小可表示值,在实现定义的方式。

    仅当您的C编译器支持附件F:IEC 60559浮点运算时,strtod才能保证符合IEEE 754(IEC 60559和IEEE 754等效):

      

    浮动常量以及&lt; stdlib.h&gt;,&lt; stdio.h&gt;和&lt; wchar.h&gt;中的strtod,strtof,strtold,fprintf,fscanf和相关库函数的转换时间转换提供IEC 60559二进制十进制转换。

  3. 另请注意,{C}自C99(Java版本5以来)以来strtod仅支持十六进制浮点表示法。因此,请检查strtod的实施行为。