【发布时间】:2015-05-07 02:24:53
【问题描述】:
我正在做一些课本上的家庭作业,并且对某些算术运算的浮点舍入/精度有一些问题。
如果我像这样从 int 中转换了双精度数:
int x = random();
double dx = (double) x;
假设变量 y、z、dy 和 dz 遵循相同的格式。
然后会像这样的操作:
(dx + dy) + dz == dx + (dy + dz)
(dx * dy) * dz == dx * (dy * dz)
具有关联性?我知道如果我们有小数表示,那么它就不会是关联的,因为根据哪些操作数相互相加/相乘,四舍五入会丢失一些精度。但是,由于这些是从整数铸造的,我觉得精度不会成为问题,而且这些可以是关联的?
最后,我使用的教科书根本没有解释 FP 除法,所以我想知道这个说法是否正确,或者至少只是浮点除法的一般工作原理:
dx / dx == dz / dz
我在网上查到了这个,我在某些方面读到,比如像 3/3 这样的运算可以产生 .999...9,但是没有足够的信息来解释这是如何发生的,或者它是否会随着其他除法运算而变化.
【问题讨论】:
-
一个好的编译器应该能够识别 dx/dx 而不是真正发出除法指令。
-
您可以将 2^53 + 1 以内的任何值精确地表示为双精度值。除此之外,您会遇到舍入错误,即使对于整数类型也是如此。 stackoverflow.com/a/1848762/141172
-
你可能记得,从你上小学的时候起,一个数字除以自身就是 1,所以比较“可能”有效。但是,一般来说,浮点数不应该使用'=='来比较,获取绝对值,获取差异,检查差异是否小于某个阈值
-
(dx * dy) * dz == dx * (dy * dz)如果double的精度 int 精度的两倍,则会出现问题——这种情况经常发生。(dx + dy) + dz == dx + (dy + dz)不太可能成为问题,因为double精度肯定超过int精度 + 1。dx / dx == dz / dz明显的问题应该是dx==0或dz==0。 -
当
dx * dy和dy * dz大于2^53时,可能存在精度问题。double dx = (double)(INT_MAX); double dy = (double)(INT_MAX - 0x111111); double dz = (double)(INT_MAX - 0xabcd);为(dx * dy) * dz == dx * (dy * dz)是假的。
标签: c floating-point floating-accuracy floating-point-conversion