1

Java 语言规范第 3.10.2 点声明浮点值按照 IEEE 754 标准中的规定进行转换。对于strtod,C 标准指定函数如何将文本转换为浮点值。关于表示本身,两者似乎涵盖了相同的情况。我不确定的是,四舍五入规则如何?Java 编译器的转换是否与实际转换不同strtod

背景是我想编译为 Java 字节码代码,因此需要将浮点/双精度值的文本表示转换为类文件中的表示。

例如,这个 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 评论的那样,当以全精度打印出值时(我通过 settings 这样做std::cout.precision()),值是相等的,所以我假设转换导致相同的值。我想我会为此做一个测试。:-)

4

1 回答 1

1

是的,有区别。这是我能找到的两个。

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

    允许在表示整数部分的数字之间、表示小数部分的数字之间以及表示指数的数字之间使用下划线作为分隔符。

    在您的情况下,这应该不是问题。你只需要去掉所有的下划线。

  2. Java 强制执行 IEEE 754 浮点算法的四舍五入规则。来自Java 规范(语言规范指的是Double.valueOf):

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

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

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

    仅当您的 C 编译器支持Annex F: IEC 60559 floating-point algorithm 时strtod才保证符合 IEEE 754(IEC 60559 和 IEEE 754 是等效的):

    <stdlib.h>、<stdio.h> 和 <wchar.h> 中的浮点常量和 strtod、strtof、strtold、fprintf、fscanf 和相关库函数的转换时间转换提供 IEC 60559 二进制-十进制转换。

另请注意,strtod仅从 C99 开始支持十六进制浮点表示法(Java 从版本 5 开始)。因此,请检查您的实现strtod行为。

于 2015-11-26T12:28:09.140 回答