Just My Life & My Work

[C++] 精準度 (Precision)

今天56級吳同學長來演講Foundations of Interval Computation
因為他是數學系出身,
所以內容大部分包含數學,
許多數學式子我可以不懂:P
但有一個演算法卻讓相當感興趣!

/**
Theme: Precision
Date: 100/03/30
compiler: Dev C++ 4.9.9.2
Author: ShengWen
Blog: https://cg2010studio.wordpress.com/
*/
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
	long double X=2,Y=1;
	int pass=0;
	cout<<setprecision(30);
	while(X>1){
		pass++;
		Y*=0.5;
		X=Y+1;
		cout<<"pass="<<pass;
		cout<<" X="<<X<<endl;
	}

	system("pause");
	return EXIT_SUCCESS;
}

猜猜看此While迴圈會無窮執行下去嗎?

pass=1 X=1
請按任意鍵繼續 . . .

哈~若把int改成float呢?

pass=1 X=1.5
pass=2 X=1.25
pass=3 X=1.125
pass=4 X=1.0625
pass=5 X=1.03125
pass=6 X=1.015625
pass=7 X=1.0078125
pass=8 X=1.00390625
pass=9 X=1.001953125
pass=10 X=1.0009765625
pass=11 X=1.00048828125
pass=12 X=1.000244140625
pass=13 X=1.0001220703125
pass=14 X=1.00006103515625
pass=15 X=1.000030517578125
pass=16 X=1.0000152587890625
pass=17 X=1.0000076293945312
pass=18 X=1.0000038146972656
pass=19 X=1.0000019073486328
pass=20 X=1.0000009536743164
pass=21 X=1.0000004768371582
pass=22 X=1.0000002384185791
pass=23 X=1.0000001192092896
pass=24 X=1
請按任意鍵繼續 . . .

接著把float改為double試試看。
因為pass24之前一模一樣,
所以只貼之後的結果。

pass=24 X=1.0000000596046448
pass=25 X=1.0000000298023224
pass=26 X=1.0000000149011612
pass=27 X=1.0000000074505806
pass=28 X=1.0000000037252903
pass=29 X=1.0000000018626451
pass=30 X=1.0000000009313226
pass=31 X=1.0000000004656613
pass=32 X=1.0000000002328306
pass=33 X=1.0000000001164153
pass=34 X=1.0000000000582077
pass=35 X=1.0000000000291038
pass=36 X=1.0000000000145519
pass=37 X=1.000000000007276
pass=38 X=1.000000000003638
pass=39 X=1.000000000001819
pass=40 X=1.0000000000009095
pass=41 X=1.0000000000004547
pass=42 X=1.0000000000002274
pass=43 X=1.0000000000001137
pass=44 X=1.0000000000000568
pass=45 X=1.0000000000000284
pass=46 X=1.0000000000000142
pass=47 X=1.0000000000000071
pass=48 X=1.0000000000000036
pass=49 X=1.0000000000000018
pass=50 X=1.0000000000000009
pass=51 X=1.0000000000000004
pass=52 X=1.0000000000000002
pass=53 X=1
請按任意鍵繼續 . . .

再進一步將double改成long double
pass53之前一模一樣,
只貼之後的結果……

pass=53 X=1
pass=54 X=1
pass=55 X=1
pass=56 X=1
pass=57 X=1
pass=58 X=1
pass=59 X=1
pass=60 X=1
pass=61 X=1
pass=62 X=1
pass=63 X=1
pass=64 X=1
請按任意鍵繼續 . . .

在數學上的實數若跑此迴圈,
必然不可能跳出迴圈,
然而因為電腦無法精準儲存【小數】,
若數字太小就會被忽略。
很遺憾setpresion最高16位數,
無法顯示更小的小數位,
不過就連最強的float double都無法維持迴圈,
這一點真的很耐人尋味呢!
可能的影響就是美國曾經把火箭發射到火星
結果火箭在中途訊號就消失了,
原因是一部分零件使用「英制」另一部分使用「公制」,
使得精準度無法相互配合,
所以才會產生無法預期的後果XD~
我想那火箭還好沒有人坐在上頭:P
講師強調這是Human mistake而不是Machine error

Comments on: "[C++] 精準度 (Precision)" (3)

  1. 未知 的大頭貼

    […] 改用double之後問題就解決了,哈~其實沒有,再去想想為什麼吧!其實之前有寫精準度 (Precision),連過去看看,就會更瞭解精準度的問題! […]

  2. frankfkc 的大頭貼

    預知詳情,請查:IEEE 754就可以完全瞭解。

回覆給ts90164 取消回覆

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

標籤雲