cyfile / Matlab-base-toolbox

本人使用Matlab基础工具箱所编写的各种代码
1 stars 0 forks source link

诡异的浮点数 #25

Open 213cy opened 3 years ago

213cy commented 3 years ago

计算机里的数都是有限的二进制位表示的,所以计算机能表示的数都是一些离散的点。

不是所有可以用字符的形式表示出来的十进制小数在计算机里都可以存储,哪怕十进制下这个数的有效位很少。

有些数必然没法表示,这时就用紧邻这个数的其他计算机能表示的数表示。

当一个数较小时,计算机会用较多的位表示小数部分。当一个数较大时,计算机用较少的位表示小数部分。

所以虽然能在计算机内部用二进制存储的数,都可以用十进制字符表示出来。但是如果该数用了较多二进制位表示小数,或是该数本来就很大的情况下,有可能需要用很多十进制位才能将此数表示出来,这时计算机仅会在屏幕上用固定数位的十进制数近似地表示计算机内部存储的数。如一个20位二进制数表示的最小小数为1/2^20;需要14位十进制数表示,而20位表示的最大的二进制整数仅需要7位十进制数表示。

web(fullfile(docroot, 'matlab/matlab_prog/floating-point-numbers.html#bqxyrhp')) https://www.mathworks.com/help/matlab/matlab_prog/floating-point-numbers.html#bqxyrhp

213cy commented 3 years ago
%% 二进制中两个bit为1的数,换算成的十进制数所占的位数(不考虑小数点的表示)
a='1001';     
b=a-'0';     
n=16;     
q=2.^(n:-1:-n)';     
b*q(1:4)  %5位     
b*q(n:n+3) %3位  
format long
b*q(end-3:end) %13位

总而言之,你放到计算机里面的数和你原本想放进去的数不一定一样;你在电脑屏幕上看到的数,和计算机里面实际放着的数也可能不一样。

213cy commented 3 years ago

双精度浮点数的间隙

format long
%
18
.1
18+.1
17.2  %计算机内的这个数实际上不是17.2 
17.2==172/10 %虽然17.2不是17.2 但是17.2仍然和172/10相等

%% 双精度浮点数的间隙 
% 双精度浮点数8字节64位,其中固定1位为符号位
% 其它是 阶码位 小数位
n=10^(1/rand/rand);
floor(log2(n)) - log2(eps(n))==52
[eps(n);1/2^(52- floor(log2(n)))]

2*eps(n)==eps(2*n) 
%%%%%%%%%%% 
a=1e1.^(15:17) 
eps(a) 

[1e15 ; 1e15+0.1]
1e15==1e15+0.1

10*1e15==10*(1e15+.1) 
1e16==1e16+1
10*1e15+1==10*(1e15+.1) 

[1e16 ; 1e16+1 ; 1e16+2]
1e16==1e16+1
1e16==1e16+2

1e17==1e17+8
1e17==1e17+9
213cy commented 3 years ago

浮点数的一些诡异现象

1-(.1+.1+.1+.1+.1+.1+.1+.1+.1+.1)
%
0:0.5:1-eps
%
floor(1.9999999999999999)
floor(1.999999999999999)
%
n=30;aaa=rand(1,n);bbb=rand(2*n,1);
aaa([1:n,n:-1:1])*bbb==aaa([1:n,n:-1:1])*flipud(bbb) %结果不一定
%
b=linspace(0,1,101);
a=0:0.01:1;
all(a==b)
all(a-b<eps)
ind=(a~=b);
[a(ind);b(ind)]
%
a=rand(4);
isequal(pow2db(a),10*log10(a))
isequal(pow2db(a),10*log10(a)+300-300)