2016-03-05 72 views
-1

我有一個功能,如:精度損失?

double calc(double x); 

難道我失去精度所有這些表述的:

double y1 = calc(1.0/3); 
double y2 = calc(1.0/3.0); 

這些是更準確:

double y3 = calc(static_cast<double>(1)/3) 
double y4 = calc(static_cast<double>(1)/static_cast<double>(3)) 

編輯

對不起,我有他在這裏錯了數字。

但是,我的意思是說是1.0解釋爲floatdouble並且總是這樣或者它是否依賴於某些編譯器標誌?如果它是float,那麼1.0/3也將是float,然後才轉換爲double。如果是這種情況,會導致精度損失,不是嗎?

EDIT 2

我與g++測試這一點,事實證明,如果程序與-fsingle-precision-constant標誌編譯,你丟失精度。

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

long double calc(long double val) 
{ 
    return val; 
} 
int main() { 
    std::cout.precision(std::numeric_limits< long double >::max_digits10); 

    std::cout << calc(1.0/3.0) << std::endl; 
    std::cout << calc(static_cast<float>(1)/3) << std::endl; 
    std::cout << calc(static_cast<double>(1)/3) << std::endl; 
    std::cout << calc(static_cast<long double>(1)/3) << std::endl; 
    std::cout << typeid(1.0).name() << std::endl; 

    return 0; 
} 

的結果是,

0.333333343267440795898 
0.333333343267440795898 
0.33333333333333331483 
0.333333333333333333342 
f 

所以,我決定用static_cast< long double >(1)/3是在安全方面。

+0

Dunno。當你嘗試時發生了什麼? –

+0

否............. –

+3

所有這些表達式都會導致相同的結果,完全沒有精度損失。 – Paraboloid87

回答

3

您所顯示的任何替代方法都不會導致精度的損失[至少在編譯器不執行標準所說的應該做的事情的情況下]。也就是說,所有二元運算符的一個操作數是double,另一方自動提升到double [並且一般來說,當兩個操作數的大小不同時,它們會被提升爲較大的]。

特別是,整數值[低於尾數的位數]總是精確表示。

[顯然,我們不知道什麼calc與您輸入的內容 - 這可能是任何來源和各種錯誤,但我假設你實際上是在問3.0/8.0總是會在案件0.375你建議 - 當然3/8將導致零,因爲這是雙方整數應答於原來的問題

編輯正在編輯:

如果代碼說1.1.00.3.3,它是double 。如果你寫0.5f,這是一個float。根據以上規則,1.0/3將是double(1.0)/double(3.0)的結果。

編譯器在技術上有可能僅支持一種浮點類型,有3種不同的寫入方式--C和C++標準沒有要求double的位數多於float

+0

我編輯了這個問題。你介意再看看並修改你的答案嗎? – Eliad

+0

仍然適用。至於爲什麼,我補充了一些澄清。 –

0

y1的常量表達式是隱含轉換爲doubley2的常數表達式已經是double

你正在做y3y4什麼是定義常量整數值,並將其強制轉換爲double,當你可以簡單地定義一個雙精度浮點常量,你已經做了。

+0

更準確一點,對於'y1','8'(隱含地)轉換爲'double'以匹配'3.0'。把這兩個雙打分開的結果是雙重的;那裏不需要轉換。 –