2

关于这个主题有很多问题(和答案),但我太厚了,无法弄清楚。在 C 中,对于给定类型的浮点数,比如 double:

double x;
scanf("%lf", &x);

scanf是否有一种通用方法来计算传递给的小数字符串与现在的内部表示之间的误差的上限(尽可能小)x

如果我理解正确,有时会出现错误,它会随着小数部分的绝对值的增加而增加(换句话说,0.1 会有点偏离,但 100000000.1 会偏离更多)。

4

2 回答 2

1

C 标准的这一方面的规定稍有不足,但您可以预期从十进制转换到原始最后位置的double一个单位内。

您似乎正在寻找转换绝对误差的界限。有了上面的假设,你可以计算出这样的界限 a doubleas DBL_EPSILON * xDBL_EPSILON通常为 2^-52。

可以按如下方式计算转换期间可能产生的错误的更严格界限:

double va = fabs(x);
double error = nextafter(va, +0./0.) - va;

最佳转换函数可确保在默认舍入到最近模式下转换为半个 ULP。如果您使用具有此保证的转换函数,您可以将我提供的界限除以二。


以上适用于以十进制表示的原始数字为 0 或其绝对值介于DBL_MIN(约 2*10^-308) 和DBL_MAX(约 2*10^308) 之间的情况。如果非空十进制数的绝对值小于DBL_MIN,则绝对误差仅以 为界DBL_MIN * DBL_EPSILON。如果绝对值高于DBL_MAX,则转换的结果可能是无穷大。

于 2013-05-23T13:53:18.457 回答
0

您不能以 10 为底来考虑这一点,错误以 2 为底,它不一定指向以 10 为底的特定小数位。

您的问题有两个潜在问题,首先 scanf 采用 ascii 字符串并将其转换为二进制数,这是一个使用许多 C 库的软件。例如,我已经看到编译时解析与运行时解析在同一系统上给出不同的转换结果。因此,就错误而言,如果您想要一个确切的数字,请自行转换并将该二进制数放入寄存器/变量中,否则接受您通过转换获得的结果并了解可能会出现您没想到的转换的舍入或剪裁(这会导致准确性问题,您没有得到预期的数字)。

第二个也是真正的问题 Pascal 已经回答了。如果二进制位置,你只有 x 数。就小数而言,如果您有 3 个小数位,则数字 1.2345 必须表示为 1.234 或 1.235。如果您有 3 位尾数,则二进制相同,则 1.0011 是 1.001 或 1.010,具体取决于舍入。IEEE 浮点数的尾数长度有据可查,你可以简单地用谷歌搜索每个精度有多少二进制位。

于 2013-05-23T14:15:29.663 回答