簡體   English   中英

C float 初始化結果出乎意料

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM