簡體   English   中英

是否可以計算 C 中小數點后的位數?

[英]Is it possible to count the number of digits after decimal point in C?

我必須計算小數點后的位數。 我找到了一個代碼,但它不適用於某些數字。 就像 2.12 一樣,它給出 output 為 7 而不是 2,但對於 2.125,它給出 output 為 3,這是正確的。

#include<stdio.h>
int main()
{
    float no =2.34;
    int count =0;
    while(no!=((int)no))
    {
        count++;
        no=no*10;
    }
    printf("\t %d \n",count);
    return 0;
}

告訴我是否有可能找出 C 中小數點后的位數。

#include <stdio.h>
#include <string.h>
int main()
{
   float no = 2.3948;
   int i = 0;
   int startCounting = 0;
   int count = 0;

   char c[500];
   sprintf(c, "%g", no);

   for(i = 0;i<strlen(c);i++)
   {
       if (startCounting == 1)
       {
           count ++;
       }
       if(c[i] == '.')
       {
           startCounting = 1;
       }
   }
   printf("\nTotal Count: %d", count);
}

二進制浮點旨在逼近實數算術。 它並非旨在記錄有關十進制數字的信息。 如果要使用十進制算術,則應使用編譯器的floatdouble精度類型以外的格式。

對於float ,您的 C 實現很可能使用 IEEE-754 基本 32 位二進制格式,也稱為 binary32。 數字 2.34 不能用這種格式表示。 float no =2.34; ,源文本2.34是一個double精度常量,十進制“2.34”轉換為可在雙精度中表示的最接近的值,即 2.339999999999999857891452847979962825775146484375,如果您的 Z0D61F8370CAD1D412F80B84D14D143E12567Z 實現使用二進制-IEEE-75E12567Z 格式關系到偶數,這兩種情況都很常見。 然后使用這個double值初始化no ,它是一個float ,因此它被轉換為可以用float格式表示的最接近的值,即 2.3399999141693115234375。

如果您的代碼正確計算了表示該數字所需的小數點后的小數位數,它將打印 22。它沒有的一個原因是因為操作no*10會產生更多的舍入錯誤。 在二進制中,十是 1010 2 ,乘以它會增加表示結果所需的位數,而不會出現舍入誤差。 由於float具有固定數量的位,因此不可能使用更多位。 所以實數結果被四舍五入以適合。 每次你的程序執行no=no*10時,它都會丟失一些關於數字的信息。

考慮到float no = 2.34; float no = 2.3399999141693115234375; no中產生完全相同的結果。 因此,從該值無法檢測到它們之間的差異。 所以沒有軟件可以判斷是用小數點后兩位數字還是小數點后22位數字初始化no

因此,沒有軟件可以告訴您原始數字有多少位,如果它所使用的只是no中的值。

可以找出會產生特定float值的最短十進制數字。 Java 和 JavaScript 以浮點數的默認格式提供此功能。 然后可以計算該數字中的數字。 但是,這僅適用於已知浮點結果等於將具有有限十進制數字的某些數字轉換為二進制浮點的結果的情況。 如果浮點結果來自計算,我們不能期望它接近一個短的十進制數字。 例如,如果no來自其他計算並且只是稍高或稍低,則float值將是相鄰值之一,即 2.340000152587890625 或 2.339999675750732421875,接近十進制數字“2.3400002”和“2.3399997”。 通常,在使用二進制浮點運算時,我們不應該期望得到簡單的十進制結果。

是否可以計算 C 中小數點后的位數?

是的。

對於整數很容易(總是零)。 對於定點數,您可以使用查找表,其中小數部分作為索引(較小的代碼,較大的表)或最低設置位的“位數”作為索引(較大的代碼,較小的表)。 這包括“大整數”和原始類型。

對於浮點類型; 你必須弄清楚你真正想要什么。 選項是:

  • 原始值中的實際位數。 在這種情況下,使用“有效數中最低設置位的位數,通過指數調整,作為表中的索引”方法(具有無窮大和 NaN 的保護措施)。

  • 有用的位數。 在這種情況下,您必須分析源代碼以確定“最壞情況錯誤”,或者編寫在運行時跟蹤錯誤以確定“實際情況錯誤”的代碼,因為所有事情都會導致您擁有的價值。 然后,您可以使用類似的“通過指數和誤差調整的最低有效位設置,作為表中的索引”方法。

  • 用於特定格式說明符的位數(例如在printf()中)。 在這種情況下,首先使用sprintf()將其轉換為字符串。 對於%f和類似以及%a和類似,在結果字符串中計算“小數點后的數字字符(如果有的話)”。 對於%e和類似的,計算“小數點之間的數字(如果有的話)和小數點后的第一個非數字字符”,然后檢查指數並分別解析,然后使用減法組合兩個結果(例如1.23e-9將是2-(-9) = 11 ) 然后將結果鉗制為非負數(例如1.23e+9將是2-(+9) = -7 = no digits )。

對於大有理數(例如由三個大整數構成,如“ numerator/divisor << exponent ”); 你必須弄清楚你真正想要什么。 選項是:

  • 原始值中的實際位數。 這是“非常復雜的”(例如,對於像1/3這樣的數字,答案可能是無窮大)。

  • 有用的位數。 在這種情況下,您可能必須分析源代碼以確定“最壞情況錯誤”並使用它來調整“原始值中的實際位數”。 請注意,對大有理數的運算通常根本沒有任何錯誤。 但是用於創建/初始化大有理數的值的轉換會出現錯誤。

  • 如果打印該值,將使用的位數。 這取決於打印它的代碼,但您可以使用類似的方法(轉換為字符串,然后解析字符串)作為浮點數。

警告:不要被評論中的人誤導。 有2個問題:

  • 將十進制轉換為浮點數; 這是不精確的,如果您不知道,可能會產生“不直觀”的結果; 與您提出的問題在技術上不相關

  • 將浮點數轉換回十進制數(並計算小數點后的數字); 這是(可以)精確的。 這是您的問題所要求的唯一內容; 答案是完全有可能(而且不一定很難)。

請注意,您的原始代碼對於某些浮點值確實可以正常工作(例如,如果您原諒舍入錯誤,則對於值 2.12 確實可以正常工作 - Eric 的回答是正確的); 而且您只認為它不起作用是因為不相關的“將十進制轉換為浮點”問題。 然而; 對於太大而無法放入int的值,您的原始代碼將無法正常工作。 要處理float可以具有的所有值(例如,包括FLT_MAX ),您需要一個大約 150 位的 integer 類型,這在 C 中作為原始類型不存在,因此您需要使用某種“大整數" 代碼/庫或我描述的方法。

更加具體; 可以存儲在float中的每個“位組合”要么是無窮大、NaN、零、小數點后具有可精確確定的位數的“正常”,要么是“次正常”可以精確確定小數點后的位數; 限制是最小幅度的非零值(假設 IEEE-754 約為 1.4013e-45),它在小數點后具有任何浮點數可以具有的最多位數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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