[英]c# print float values with more precision
我想以比默認值更高的精度打印浮點數。
例如,當我從浮點數打印 PI 的值時,我得到 6 位小數。 但是,如果我將浮點數中的相同值復制到雙精度數中並打印出來,則會得到 14 位小數。
為什么在打印相同的值但作為雙精度值時會獲得更高的精度?
在打印浮點數時如何讓 Console.WriteLine() 輸出更多小數,而無需先將其復制到雙精度中?
我也試過 0.0000000000 但它沒有寫得更精確,它只是添加了更多的零。 :-/
我的測試代碼:
float x = (float)Math.PI;
double xx = x;
Console.WriteLine(x);
Console.WriteLine(xx);
Console.WriteLine($"{x,18:0.0000000000}"); // Try to force more precision
Console.WriteLine($"{xx,18:0.0000000000}");
輸出:
3,141593
3,14159274101257
3,1415930000 <-- The program just added more zeroes :-(
3,1415927410
我也嘗試在https://www.h-schmidt.net/FloatConverter/IEEE754.html輸入 PI
PI 的二進制浮點表示為 0b01000000010010010000111111011011
所以值是:2 * 0b1.10010010000111111011011 = 2 * 1.57079637050628662109375 = 3.1415927410125732421875
所以有更多的小數要輸出。 我如何讓 C# 輸出整個值?
浮點數不再有精度。 當您將其轉換為double
,准確性會更差,即使精度(位數)增加了 - 基本上,您在 double 打印中看到的所有額外數字都是轉換工件 - 它們是錯誤的,只是最好的表示給定浮點數,您可以獲得雙精度數。 這與二進制浮點數的工作方式有關。
讓我們看看浮點數的二進制表示:
01000000010010010000111111011100
第一位是符號,接下來的八位是指數,其余的是尾數。 當我們將它轉換為 double 時,我們會得到什么? 指數保持不變,但尾數用零填充。 但這實際上改變了數字 - 你得到3.1415929794311523
(四舍五入,與二進制浮點數一樣)而不是正確的3.14159265358979
pi 的雙3.14159265358979
值。 你會得到更精確的錯覺,但這只是錯覺——數字並不比以前更准確,你只是用噪音代替了零。
浮點數和雙精度數之間沒有 1:1 的映射。 同一個浮點值可以用許多不同的雙精度值來表示,數字的十進制表示可以相應地改變。 如果您關心小數精度,則每次將float
為double
都應進行舍入運算。 請考慮以下代碼:
double.Parse(((float)Math.PI).ToString())
我沒有將浮點數轉換為雙精度數,而是首先將其更改為十進制表示(在字符串中),然后從中創建雙精度數。 現在,不是有一個“截斷”的雙精度數,而是一個適當的雙精度數,它不會涉及額外的精度; 當你打印出來時,你會得到3.1415930000
。 當然,仍然四舍五入,因為它仍然是二進制->十進制轉換,但不再假裝比實際精度更高 - 舍入發生在比浮點版本晚的數字,零實際上是零,除了最后一個(僅近似為零)。
如果您想要真正的十進制精度,您可能需要使用十進制類型(例如int
或decimal
)。 float
和double
都是二進制數,只有二進制精度。 有限的十進制數在二進制中不一定是有限的,就像有限的三進制數在十進制中不一定是有限的一樣(例如,1/3 沒有有限的十進制表示)。
c# 中的浮點數精度為 7 位,僅此而已。 這意味着小數點前 1 位數字和后 6 位數字。
如果您的輸出中有更多數字,則它們可能完全錯誤。
如果您確實需要更多數字,則必須使用精度為 15-16 位的 double 或具有 28-29 位的十進制。
您可以輕松驗證 PI 的數字與您的輸出略有不同。 正確的前 40 位數字是: 3.14159 26535 89793 23846 26433 83279 50288 4197
打印小數點后 6 位的值。
Console.WriteLine("{0:N6}", (double)2/3);
輸出 :
0.666667
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.