使用这个简单的程序:
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(int argc, char* argv[]) {
double a = 10.333300;
double b = 10.333300000000000;
double c = nextafter(a,a+0.5);
double d = nextafter(b,a+0.5);
printf("[%012.12f]\n[%012.12f]\n[%012.12f]\n[%012.12f]\n", a, b, c, d);
return 0;
}
打印输出符合预期:
$ ./nextafter
[10.333300000000]
[10.333300000000]
[10.333300000000]
[10.333300000000]
但是,真正的价值并不是这些:
(gdb) p a
$1 = 10.333299999999999
(gdb) p b
$2 = 10.333299999999999
(gdb) p c
$3 = 10.333300000000001
(gdb) p d
$4 = 10.333300000000001
现在,这似乎是由the way floats and doubles are represented引起的,我正在使用带有旧RHEL的64位x86 VM。使用nextafter
确实可以尽可能地解决问题,但它提出了一些问题:
无法将0.3333用“零填充”到右边的零,直到它形成一个有效的二进制数(在这种情况下,我猜是0.333300000000001)?即默认情况下可以使用nextafter
吗?
有没有办法设置双默认精度(在这种情况下为10或11)?
是否有可以精确表示浮点数的架构?
或者说,为什么10.3333会立即四舍五入到10.3332(9)而不是将其四舍五入到nextafter
版本?
答案 0 :(得分:0)
发布的格式字符串正在使用:%012.12f
这会限制数字量太多。
建议使用格式字符串,如:%020.20f
,然后输出将更符合您的要求。即。
[10.33329999999999948557]
[10.33329999999999948557]
[10.33330000000000126192]
[10.33330000000000126192]