[英]C float initialization result is unexpected
Visual Studio 2019 Community 浮點變量不是我將其初始化的對象。 為了避免截斷,我讓它不那么精確。 這不是“可控”嗎?
試圖強制 init 以其他方式四舍五入
int main()
{
// where did my 6 go?
float b = 80.123456F;
printf("b:[%f]\n", b);
// rounds up
float c = 80.1234569F;
printf("c:[%f]\n", c);
// rounds up
float d = 80.1234561F;
printf("d:[%f]\n", d);
// appends a 1
float e = 80.12345F;
printf("e:[%f]\n", e);
// prints what's initialized
float f = 80.123451F;
printf("f:[%f]\n", f);
// prints what's initialized
float g = 80.123459F;
printf("g:[%f]\n", g);
}
b:[80.123459]
c:[80.123459]
d:[80.123459]
e:[80.123451]
f:[80.123451]
g:[80.123459]
我已經開始使用調試器並編寫它以滿足 SO 要求。 在我的情況下,調試器匹配打印
浮點數最多只能精確到 7 位有效數字。 不是 7位十進制數字。 80.123456F 有 8 位有效數字,所以這是行不通的。
雖然 80.12345 只有 7 位有效數字,但實際上最終大約為 80.1234512329101562。 只要您不嘗試打印比它更多的數字,就可以了。 不幸的是, %f 總是在小數點后打印 6 位數字。 在這種情況下,這是一個更有意義的。 你會用 %g 做得稍微好一點,你可以在其中指定有效數字的數量。
兩個問題:
帶有%f
轉換說明符的printf
執行自己的浮點值舍入以供顯示。 您可以使用精度說明符控制顯示小數點后的位數: printf( "%.8f\\n", b );
將打印小數點后最多 8 位數字,並且printf( "%.16f\\n", a);
將打印 16。不過不要相信顯示的值,因為...
無限數量的實數值無法放入有限數量的位中,因此大多數實數值無法准確表示 - 您得到的近似值僅適用於如此多的十進制數字。 單精度float
類型不能保證超過 6 到 7 位十進制數字的精度(這不僅僅是小數點后面的位數,而是總位數)。 double
給你類似 10 到 11 位的數字。 如果您需要表示具有多位精度(超過 12 位左右)的值,那么您需要跳過本機浮點類型並使用第三方多精度庫。
這個問題的解決方案可能是改變數據類型。 盡管double
操作方式與float
相同,通過一組有限的有理數來逼近大范圍的實數,但雙精度如此接近以至於舍入誤差不太可能重要。
例如,最接近實數 80.123456 的float
值是 80.12345123291015625 和 80.1234588623046875。 最接近 80.123456 的double
精度值是 80.123456000000004451067070476710796356201171875 和 80.12345599999999024021235500000445106707073073233459999999900000004737373737837873733567787963562011718753。
在您處理非常大的非常低精度的數字集的情況下, float
確實有其用途,但double
是更普遍有用的類型。 使用double
將物理量寫入程序時,測量誤差將超過舍入誤差。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.