我想乘兩個float
S作爲如下:乘以兩個浮體不會給確切的結果
float number1 = 321.12;
float number2 = 345.34;
float rexsult = number1 * number2;
我想看到的結果是110895.582,但是當我運行的代碼,它只是給了我110896大部分時間我都有這個問題。任何計算器都會給我所有小數點的確切結果。我怎樣才能達到那個結果?
編輯:這是C代碼。我正在使用XCode iOS模擬器。
我想乘兩個float
S作爲如下:乘以兩個浮體不會給確切的結果
float number1 = 321.12;
float number2 = 345.34;
float rexsult = number1 * number2;
我想看到的結果是110895.582,但是當我運行的代碼,它只是給了我110896大部分時間我都有這個問題。任何計算器都會給我所有小數點的確切結果。我怎樣才能達到那個結果?
編輯:這是C代碼。我正在使用XCode iOS模擬器。
有很多四捨五入的事情。
float a = 321.12; // this number will be rounded
float b = 345.34; // this number will also be rounded
float r = a * b; // and this number will be rounded too
printf("%.15f\n", r);
經過三次單獨的圓整後我得到了110895.578125000000000。
如果你想超過6個十進制數字的價值的精確度,你會有使用double
,而不是float
。 (請注意,我說的「小數位數值得」,因爲你沒有得到十進制數字,你得到的二進制)。既然這樣,1/2 ULP誤差(最壞情況開往完美四捨五入的結果)大約是0.004。
如果你想要的是四捨五入的十進制數字,你將不得不使用一個專門的小數庫這樣的任務。 A double
對科學家來說具有足夠的精度,但如果你用錢工作,所有事情都必須100%準確。沒有浮點數的錢。
不像整數,浮點數採取一些實實在在的工作,才能讓習慣了他們的陷阱。請參閱「What Every Computer Scientist Should Know About Floating-Point Arithmetic」,這是該主題的經典介紹。
編輯:其實,我不確定代碼輪了三次。由於a
和b
的常量可能會先舍入爲雙精度,然後在存儲時將它們舍入爲單精度,這可能會輪到五次次。但我不太清楚C這部分的規則。
「它可能四捨五入」確切地說,但對於大多數十進制數,首先舍入爲「double」,然後是「float」與直接舍入爲「float」相同。當我正在尋找1到2之間的無辜十進制數字時,出於http://blog.frama-c.com/index.php?post/2011/11/08/Floatingpoint -quiz,我必須在點後使用14位數字。我找不到只有13位數字。 – 2012-07-08 13:00:53
由於您使用的是C,你可以很容易地通過使用「%.xf」,其中x是想要的精確設定的精度。
例如:
float n1 = 321.12;
float n2 = 345.34;
float result = n1 * n2;
printf("%.20f", result);
輸出:
110895.57812500000000000000
但是,請注意float
只給出精確六位數。爲更好的精確度使用double
。
printf也做了一些四捨五入。考慮http://codepad.org/LLweoeHp:
float t = 0.1f;
printf("result: %f\n", t);
--
result: 0.100000
好吧,它看起來很好。爲什麼?因爲printf默認了一些精確度並捨去了輸出。我們撥打小數點後50位:http://codepad.org/frUPOvcI
float t = 0.1f;
printf("result: %.50f\n", t);
--
result: 0.10000000149011611938476562500000000000000000000000
這是不同的,不是嗎? 625之後,浮動量不足以保存更多數據,這就是爲什麼我們會看到零。 double可以容納更多的數字,但是二進制中的0.1不是有限的。雙不得不放棄,最終:http://codepad.org/RAd7Yu2r
double t = 0.1;
printf("result: %.70f\n", t);
--
result: 0.1000000000000000055511151231257827021181583404541015625000000000000000
在你的榜樣,獨自321.12足以引起麻煩:http://codepad.org/cgw3vUKn
float t = 321.12f;
printf("and the result is: %.50f\n", t);
result: 321.11999511718750000000000000000000000000000000000000
這就是爲什麼一個具有呈現在他們面前圍捕浮點值給人類。
計算器程序根本不使用浮動或雙打。它們實現十進制數字格式。例如:
struct decimal
{
int mantissa; //meaningfull digits
int exponent; //number of decimal zeroes
};
需要重新創建所有操作的Ofc:加法,減法,乘法和除法。或者只是尋找一個小數庫。
不,1.0將永遠不會是1.0。四捨五入是以一種非常可預測的方式完成的,任何低於2^24的整數在每一次都會非常準確。 – 2012-07-08 09:25:36
@DietrichEpp:我寫到1.0是一個虛構的例子。 – 2012-07-09 15:53:36
很容易選擇0.1或1/3或100000001.有很多非虛構的例子。 – 2012-07-09 16:14:37
你永遠不會得到確切的結果。
首先,number1≠321.12,因爲該值不能在base-2系統中精確表示。你需要無限的位數。
這同樣適用於number2≠345.34。
所以,你首先從不精確的值開始。
然後,產品將變爲四捨五入,因爲乘法會使有效位數增加一倍,但如果乘上浮點數,產品必須再次存儲在float
中。
您可能希望爲數字使用基於10的系統。或者,如果您的數字只有小數點的兩位十進制數,則可以使用整數(在這種情況下,32位整數就足夠了,但最終可能需要64位):
32112 * 34534 = 1108955808
這代表321.12 * 345.34 = 110895.5808。
這是C還是Java?它可以來自你所展示的。 – Mysticial 2012-07-08 09:03:07
你應該使用'double'而不是'float'。 – Mysticial 2012-07-08 09:03:29
我也用過雙倍,結果相同。 – ugur 2012-07-08 09:05:01