English 中文(简体)
双重精准行为。 需要解释
原标题:Double precision strange behaviour. Need an explanation

该法典:

#include <stdio.h>
#include <math.h>

static double const x = 665857;
static double const y = 470832;

int main(){
    double z = x*x*x*x -(y*y*y*y*4+y*y*4);
    printf("%f 
",z);
    return 0;
}

我很想知道,如果用32台借机(或像我这样在64台借机上悬挂——m32国旗)与海合会4.6相配,那么该代码就印刷了“0.0”。 就我所知的浮动点业务而言,可能过度流入/渗入或与它们失去精确性,但......如何?

提前感谢。

最佳回答

这是因为,第754号电子计算法是按正常格式计算的浮动点数。 浮动或翻一番,或者任何其他符合要求的代表情况如下:

1.xxxxxxxxxxxxxxxxxxx * 2^exp

>>> 代码>是红土的分部分,因此,红土本身始终处于[1、2)。 总分类为1的分类部分没有储存在代表处。 <代码>x bits 界定了准确性。 http://code>double。 支出以抵消形式储存(为了获得其价值,必须减去1023美元),但现在这无关紧要。

665857^4 in 64-bit IEEE 754 is:

0 10001001100 (1)0100110100000001111100111011101010000101110010100010
+ exponent    mantissa

(第一种轨道是:0=正值,1 - 负;括号中的比值没有实际储存)

In 80-bit x86 extended precision it is:

0 10001001100    (1)0100110100000001111100111011101010000101110010100010
0 100000001001100 1 010011010000000111110011101110101000010111001010000111000111011

(在分类部分明确属于代表部分的情况下——偏离了ISO 754;我把红issa调为清晰度)

4*470832^4,载于64-bitIE 754和80-bit x86的精度:

0 10001001100    (1)0100110100000001111100111011101001111111010101100111
0 100000001001100 1 010011010000000111110011101110100111111101010110011100100010000

4*470832^2,载于64-bitIE 754和80bit x86的精度:

0 10000100110    (1)1001110011101010100101010100100000000000000000000000
0 100000000100110 1 100111001110101010010101010010000000000000000000000000000000000

当你总结最后两个数字时,程序如下:小值调整后,其权宜之计与大值相对应,而红利则转向权利,以保持价值。 由于两个分位数相差38个,小数的红土将38个分位移至正确点:

第470832^2*4号,经调整的64-bit、754和80-bit x86号:

 this bit came from 1.xxxx ------------------------------v
0 10001001100    (0)0000000000000000000000000000000000000110011100111010|1010
0 100000001001100 0 0000000000000000000000000000000000000110011100111010101001010101

如今,这两种数量都有同样的权宜之计,其红外线可以传承:

0 10001001100 (1)0100110100000001111100111011101001111111010101100111|0010
0 10001001100 (0)0000000000000000000000000000000000000110011100111010|1010
--------------------------------------------------------------------------
0 10001001100 (1)0100110100000001111100111011101010000101110010100001|1100

我保留了对酒吧权利的80项精准参数中的部分,因为内部传票的精确度为80倍。

现在,允许在64比值+80美分中的某些分位数:

minuend    0 10001001100 (1)0100110100000001111100111011101010000101110010100001|1100
subtrahend 0 10001001100 (1)0100110100000001111100111011101010000101110010100001|1100
-------------------------------------------------------------------------------------
difference 0 10001001100 (0)0000000000000000000000000000000000000000000000000000|0000

纯一! 如果你全程进行计算,你将再次获得纯0。

这里的真正问题是,在64轨精确度中不能有1.0个代表,比例为2^77,在红土中不存在77个精确度。 80轨道精确度也是如此——在红土只有63个比值,14个比值不到代表1.0的必要,考虑到2^77的幅度。

因此,这吧! 它只是科学计算这个可贵的世界,在这个世界里,你在数学课堂教学的方式没有任何作用。

问题回答

The problem is not that the numbers overflow. The problem is that doubles don t have enough precision to distinguish between the two operands of your subtraction.

<代码>x*x*x*x值为1965730060045194713601。

The value of y*y*y*y*4+y*y*4 is 196573006004558194713600.

这些数字有78个比值,只有最后一个比值不同。 双重精确数字只有53比值。 其他数字只四舍五入到53秒。

就你而言,这两家歌剧的间隔时间相同,因此其差异为0。

即便是陌生的事情,如果你稍微把你的表述改写给兹的话:

double z = x * x * x * x - ((y * y + 1) * y * y * 4);

With this change, you get 33554432! Why? Because the way intermediate results were rounded caused the last bit of the right operand to be different. The value of the last bit is 2^(78-53)=2^25.

以任意的精确度评价表达方式:

Prelude> 665857^4 - 4*(470832^4 + 470832^2)
1

由于<代码>double通常只有53个精度参数,中间结果有78个比值,精确度仅为计算结果,因此四舍五入,最后的比值在某个时候被遗忘。

There is no floating-point overflow or underflow in your code. The two quantities are of the order of 1.96573006 × 10^23, and largely fit within a double. Your example simply illustrates catastrophic cancellation, where you subtract two close quantities and the relative precision of the result becomes horrible.





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签