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()
完成的),值是相等的,所以我假设转换导致相同的价值观。我想我会为此做一个测试。 : - )
答案 0 :(得分:1)
是的,有差异。这是我能找到的两个。
Java支持数字之间的下划线。来自规范:
允许下划线作为表示整数部分的数字之间的分隔符,以及表示分数部分的数字之间以及表示指数的数字之间的分隔符。
在您的情况下,这应该不是问题。您只需剥离所有下划线。
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二进制十进制转换。
另请注意,{C}自C99(Java版本5以来)以来strtod
仅支持十六进制浮点表示法。因此,请检查strtod
的实施行为。