日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于浮点数的误差理解

發布時間:2025/4/16 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于浮点数的误差理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

拜讀了Cleve Moler寫的博客《Bank Format and Metric Socket Wrenches》,對浮點數又有了進一步的理解。原文的鏈接地址為
http://blogs.mathworks.com/cleve/2017/04/10/bank-format-and-metric-socket-wrenches/
本文的內容是對這篇文章部分翻譯以及自己的一些理解,讓大家能夠更加容易看懂。

從format bank這個問題而來

我們知道matlab中有一些命令可以控制顯示格式,比如:
format short: 默認,顯示較少的有效數字
format long:顯示較多的有效數字
format hex:用16進制顯示
format short g:用8進制顯示
這些都比較常用,在金融銀行業中用的比較多的就是format bank,這個命令保留小數點后2位(四舍五入,保留2位小數)

注意上面的命令只是用來控制顯示的格式,而不影響計算的精度

在使用format bank時可能會遇到讓你覺得奇怪的現象,如果你對計算機內的浮點數表示不了解的話。以下是一個奇怪的例子

format long x = (5:10:45)' / 1000 y = 1 + x z = 2 + x

x =

0.005000000000000
0.015000000000000
0.025000000000000
0.035000000000000
0.045000000000000

y =

1.005000000000000
1.015000000000000
1.025000000000000
1.035000000000000
1.045000000000000

z =

2.005000000000000
2.015000000000000
2.025000000000000
2.035000000000000
2.045000000000000

format bank x y z

x =
0.01
0.01
0.03
0.04
0.04

y =
1.00
1.01
1.02
1.03
1.04

z =
2.00
2.02
2.02
2.04
2.04

是不是覺很奇怪,變量x, y, z中有些數字四舍五入了,有些沒有四舍五入。其實這就是10進制小數不能完全用2進制浮點數精確表示引起的。

雖然在matlab中顯示的數字等于 0.015000000000,好像很精確了,但其實在matlab內部這個數卻還沒有達到0.015,比0.015略小一點。 下面可以證實這一點

exact_x = sym(x, 'e') exact_y = sym(y, 'e') exact_z = sym(z, 'e')

sym(x, ‘e’) 返回的就是在matlab中表示的數值x,結果的類型是一個符號數。

exact_x =
eps/2133 + 1/200
3/200 - eps/400
eps/160 + 1/40
(3*eps)/200 + 7/200
9/200 - (3*eps)/400

exact_y =

201/200 - (12*eps)/25
203/200 - (11*eps)/25
41/40 - (2*eps)/5
207/200 - (9*eps)/25
209/200 - (8*eps)/25

exact_z =

401/200 - (12*eps)/25
(14*eps)/25 + 403/200
81/40 - (2*eps)/5
(16*eps)/25 + 407/200
409/200 - (8*eps)/25

可以看到所有的數都比理論值多一點或者少一點,其實這個誤差是怎么來的,為什么會有這個誤差,其實就跟浮點數的表示有關。我很早寫過一篇關于浮點數如何表示的文章,大家可以參看一下,文章地址http://blog.csdn.net/whoispo/article/details/6312782。在下一節中,我會計算這個誤差,大家最好能夠理解浮點數的表示。

因此對于上面的變量x, y, z,有些進行了四舍五入,有些沒有的原因,就比較好理解了。數字比0.5稍小的,就舍去了,比0.5稍大的就入位。

format short signx = sign(double(exact_x - x)) signy = sign(double(exact_y - y)) signz = sign(double(exact_z - z))

signx =
1
-1
1
1
-1

signy =
-1
-1
-1
-1
-1

signz =
-1
1
-1
1
-1

等于1就表示matlab中表示值比理論值大,因此入位,等于-1就表示matlab的表示值比理論值小,就舍去。大家看看是不是和format bank顯示的結果一致。

計算浮點數的誤差

下面就來計算一下浮點數 0.1 的誤差。

我們知道0.1在1/16和1/8之間,因此可以確定0.1的浮點數的指數部分應該就是1/16,剩下的就是尾數部分。一般而言,如果不對matlab的類型做特殊說明,matlab的類型大多都是double類型。double類型的尾數部分有52位,也就是2?52,再加上指數部分的2?4,因此對于1/16到1/8之間的數,相鄰兩個數之間的間隔為2?56,也即0.1附近的數的間隔為2?56。用matlab驗證一下

eps(0.1) 2^(-56)

ans =

1.3878e-17

ans =

1.3878e-17

y = eps(x) 定義就是計算浮點數集中比x?大一點的數與x?的差值,也就是計算x附近的浮點數的間隔。注意我在這里的x右上角加了一個”*”,表示計算機中x的值。

我們知道了間隔,就很容易得到相鄰的比x小一點的數,我們記為x?,和相零的比x大一點的數了,我們記為x+x?取哪一個數,取決于x離x?近還是離x+近。

x?x+的計算

x?=floor(0.1?1/16gap)?gap+1/16
因為
floor(?1/16gap)?gap+1/16=0
所以
x?=floor(0.1gap)?gap
同理
x+=ceil(0.1gap)?gap

x = 2^(-56) symx = sym(x) x0 = floor(0.1/symx)*symx x1 = ceil(0.1/symx) * symx

x =

1.3878e-17

symx =

1/72057594037927936

x0 =

7205759403792793/72057594037927936

x1 =

3602879701896397/36028797018963968

為了計算xx?近還是離x+近,下面只能采用matlab的符號計算,為了避免丟失精度,因為x0和x1已經是符號變量了,所以可以直接構造符號變量c。

c = [x0 0.1 x1]'

c =

7205759403792793/72057594037927936
1/10
3602879701896397/36028797018963968

這里的c(2)精確等于0.1,因為這是一個符號。用vpa函數計算精確值,這是對符號數進行高精度計算的方法,可以任意指定精度

vpa(c, 50)

ans =

0.099999999999999991673327315311325946822762489318848
0.1
0.1000000000000000055511151231257827021181583404541

從這里可以看到,用雙精度浮點數確實不能精確表示0.1

double(c(1)) double(c(3))

ans =
0.1000

ans =
0.1000

x = 2^(-56); x = sym(x); e1 = (0.1 - c(1))/x; e2 = (c(3) - 0.1)/x; vpa(e1) vpa(e2)

ans =

0.6

ans =

0.4

因此可以看到x還是離x+近一點。所以0.1在計算機中的存儲的值為

x?=1/10+eps(0.1)?0.4

在計算機中

eps=eps(1.0)=2?52
eps(0.1)=2?56

因此

x?=1/10+eps/40

用matlab驗證一下

x = 0.1 e = sym(x, 'e')

x =
0.1000

e =

eps/40 + 1/10

與預想結果一致。

總結

以上是生活随笔為你收集整理的关于浮点数的误差理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。