2016-03-05 77 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'。把这两个双打分开的结果是双重的;那里不需要转换。 –