2017-09-03 87 views
0

我正在試圖找到Machine Epsilon的精度和錯誤。不使用std :: numeric_limits。我被教授給出了下面的公式:y = 1-x/2^n,n> 1。我假定y是機器Epsilon,x是1.0,n應該是精度。C++中的Epsilon計算機錯誤

這裏是我的頭文件macEpsFloat.hpp:

class MacEpsFloat 
{ 

public: 

    int precision(int n); 

private: 
    float e = 1.0; //error 
    float x = 1.0; //variable 
    float y = 0.0; //variable 
    int prec = 0; 
}; 

這裏是我的macEpsFloat.cpp文件

int MacEpsFloat::precision(int n) 
{ 
    y = 1 - (x/(1<<n)); 

    if (y == 1.0) 
    { 
     prec = n-1; 
    } 
    else 
    { 
     float error = std::abs(e - y); 
     std::cout << "Error: " << error << std::endl; 
     ++n; 
     precision(n); 
    } 
    return prec; 
} 

這裏的main.cpp

#include <iostream> 
#include "macEpsFloat.hpp" 


int main() 
{ 

    MacEpsFloat a; 

    std::cout << "Precision Float: " << a.precision(1) << std::endl; 
    std::cout << std::endl; 

} 

變量y設定爲1.0,e設定爲1.0,n設定爲1.

我得到以下輸出:

error: 0.5 
error: 0.25 
error: 0.125 
error: 0.0625 
error: 0.03125 
error: 0.015625 
error: 0.0078125 
error: 0.00390625 
error: 0.00195312 
error: 0.000976562 
error: 0.000488281 
error: 0.000244141 
error: 0.00012207 
error: 6.10352e-05 
error: 3.05176e-05 
error: 1.52588e-05 
error: 7.62939e-06 
error: 3.8147e-06 
error: 1.90735e-06 
error: 9.53674e-07 
error: 4.76837e-07 
error: 2.38419e-07 
error: 1.19209e-07 
error: 5.96046e-08 
Precision Float: 24 

Wiki有2對答案的浮動。第一個是1.19209e-07,精度爲23,另一個是5.96046e-08,精度爲24.

我在這裏看到兩個答案,所以我知道我在正確的軌道上。但是,我不明白爲什麼我的遞歸算法會再次分割問題。我相信我正在尋找的答案是5.96046e-08或1.19209e-07,如果我將它乘以2.但是,我不確定我的代碼中爲什麼它再次執行一次會出現什麼問題。

我遇到的另一個問題是這段代碼不適用於任何原因的雙打。所以我想知道這是爲什麼。把它放進一個while循環,看看是否有什麼變化,會更好嗎?或者我有機器Epsilon公式錯誤?

任何幫助,將不勝感激。

編輯:添加編譯代碼。

編輯2:我解決了我最初的問題,錯誤仍在計算中,我只是把這段代碼扔到else語句中,現在它計算浮點數就好了。但是,當我將所有類型更改爲雙打時,它會出現故障,我不知道爲什麼它會這樣做。

+2

應用通常的調試過程來添加更多的打印或逐步通過您的代碼。在這裏也包括一個完整的程序標準,可以剪切並粘貼到文件中並進行編譯。 –

+0

@KhouriGiordano我現在已經做了一個編輯,我已經添加了頭文件和main.cpp文件。我已經通過調試器加入了代碼。 if語句在運行此代碼時完全應該做什麼。但是,它在第​​24次迭代中不完全等於1。它等於0.9999981之類的東西,因此它回到遞歸代碼中,當它再執行1次時,它不可避免地再次將其分開並將1加1。留下我的錯誤爲0,我的迭代爲25. – Sailanarmo

+1

這不僅僅是一個邏輯錯誤?當'error = 0'的時候,你把精度設置爲'n'。但是'error = 0'也是每個'n'大於那個。我認爲精度是'n'的最後一個值,'error!= 0':'epsilon'是可以加到'1'的'2'的最小功率,使得結果可以與'1 '。 – Walter

回答

0

我找到了我的問題的答案。

我改變了我的函數來計算else語句裏面的錯誤。這樣它會給我錯誤而不是之後。

我用雙變量解決了Seg錯誤,因爲我沒有意識到(因爲我的機器的尺寸或實際架構,我只能移動32次)。因此,在遞歸的32次迭代之後,它會拋出隨機數,最終被零除,導致分段錯誤。代碼現在看起來像這樣:

int MacEpsFloat::precision(int n) 
{ 
    y = 1 - (x/(std::pow(2,n))); 

    if (y == 1.0) 
    { 
     prec = n-1; 
    } 
    else 
    { 
     double error = std::abs(e - y); 
     std::cout << "Error: " << error << std::endl; 
     ++n; 
     precision(n); 
    } 
    return prec; 
} 

我沒有意識到,我只能進行位移。感謝所有幫助過的人!