2009-02-02 30 views
3

我想在特定的計算機上找到尾數位數和單位舍入數。我瞭解這些是什麼,只是不知道如何找到它們 - 儘管我知道它們可以因計算機而異。如何找到特定機器上的尾數長度?

我需要這個數字來執行數值分析的某些方面,比如分析錯誤。

我目前的想法是我可以編寫一個小的C++程序來緩慢增加一個數字,直到發生溢出,但我不確定使用什麼類型的數字。

我在正確的軌道上嗎?一個人究竟如何計算這個?

+0

在某些系統上,模擬某些浮點類型(特別是那些沒有FPU的系統,當然)。 – strager 2009-02-02 02:24:24

回答

5

我會認爲你使用的任何語言將指定如何存儲浮動。我知道Java通過使用特定的IEEE標準來做到這一點(我認爲是754)。

如果沒有指定,我認爲你可以通過加0.5到1來做你自己的檢查,看看實際的數字是否改變。如果確實如此,那麼加0.25至1,0.125到1,依此類推,直到數量不發生變化,是這樣的:

float a = 1; 
float b = 0.5; 
int bits = 0; 
while (a + b != a) { 
    bits = bits + 1; 
    b = b/2; 
} 

如果你只有3個尾數位,那麼1 + 1/16將等於1.

然後,你已經用盡了你的尾數位。

實際上您可能需要的基數是2而不是1,因爲IEEE754在開始時使用隱含的「1+」。

編輯:

它,因爲它給出63個比特爲清楚地具有4個字節的浮子系統出現上述可以具有一些問題的方法。

這是否是做與中間結果(I懷疑它因爲具有顯式轉換相同的代碼[while (((float)(a + b) != (float)(a))]具有類似的問題)或(更可能的是,我相信)的單位值a可以與更靠近位表示的可能性通過調整指數給分數b,我還不知道。

現在,最好依靠上面提到的語言信息,如使用IEEE754(如果有這些信息)。

我會留下有問題的代碼作爲警惕球員的陷阱。也許有更多浮點知識的人,我可以留下一個說明,解釋它爲什麼奇怪地行爲(沒有猜想,請:-)。

編輯2:

這段代碼通過確保中間體被存儲在浮修復它。原來Jonathan Leffler是對的 - 這是中間結果。

#include <stdio.h> 
#include <float.h> 

int main(void) { 
    float a = 1; 
    float b = 0.5; 
    float c = a + b; 
    int bits = 1; 
    while (c != a) { 
     bits = bits + 1; 
     b = b/2; 
     c = a + b; 
    } 
    printf("%d\n",FLT_MANT_DIG); 
    printf("%d\n",bits); 
    return 0; 

}

該代碼輸出(24,24),以顯示所計算的值相匹配的一個在頭文件。

雖然用C語言編寫,但它應該適用於任何語言(特別是信息在標題中不可用或憑藉它在語言文檔中指定的語言)。我只在C中測試過,因爲Eclipse需要很長時間才能啓動我的Ubuntu盒子:-)。

+0

感謝您花費額外的時間來解決最初的問題 - 我瞭解您的邏輯,並且對於初始方式爲什麼沒有給出與FLT_MANT_DIG相同的答案也感到困惑。 – 2009-02-02 05:02:09

1

對於C和擴展C++,信息位於<float.h><cfloat>標頭中。

對於C99,該信息是在該標準的5.2.4.2.2節:

  • FLT_RADIX
  • FLT_MANT_DIG
  • FLT_DIG
  • FLT_EPSILON
  • FLT_MIN_EXP
  • FLT_MIN
  • FLT_MIN_10_EXP
  • FLT_MAX_EXP
  • FLT_MAX
  • FLT_MAX_10_EXP

同樣地,對於DBL和LDBL變體,大多數這些(無DBL_RADIXLDBL_RADIX)。該標準提出了適用於IEEE 754(1999年出版的IEEE 754標準的舊版本;我相信2008年出版了新版本)的值。

+0

使用Pax提出的方法得出63的答案,然而FLT_MANT_DIG表示他的尾數有23位數字。我想有些東西我不理解,但爲什麼差異? – 2009-02-02 03:29:14

1

你可能想看看在你的C++庫<limits>

#include <iostream> 
#include <limits> 
#include <typeinfo> 

template <typename T> 
void printDetailsFor() { 
    std::cout 
     << "Printing details for " << typeid(T).name() << ":\n" 
     << "\tradix:  " << std::numeric_limits<T>::radix  << "\n" 
     << "\tradix digits: " << std::numeric_limits<T>::digits  << "\n" 
     << "\tepsilon:  " << std::numeric_limits<T>::epsilon() << "\n" 
     << std::endl; 
} 

int main() { 
    printDetailsFor<int>(); 
    printDetailsFor<float>(); 
    printDetailsFor<double>(); 
    printDetailsFor<long double>(); 
    return 0; 
} 

我認爲你要std::numeric_limits<T>::digits這應該是比尾數位的數目多一個。我的機器打印出來了:

Printing details for i: 
    radix:  2 
    radix digits: 31 
    epsilon:  0 

Printing details for f: 
    radix:  2 
    radix digits: 24 
    epsilon:  1.19209e-07 

Printing details for d: 
    radix:  2 
    radix digits: 53 
    epsilon:  2.22045e-16 

Printing details for e: 
    radix:  2 
    radix digits: 64 
    epsilon:  1.0842e-19