精度损失?

时间:2016-03-05 12:26:06

标签: c++ g++ precision

我的功能如下:

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。如果是这种情况,会造成精度损失,不是吗?

编辑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来保证安全。

2 个答案:

答案 0 :(得分:3)

您展示的任何替代方案都不会导致任何精度损失[至少在编译器执行标准应该执行的操作时不会这样做]。这是所有二元运算符,其中一个操作数是double,另一方自动升级为double [并且通常,当两个操作数大小不同时,它们被提升为更大的操作数]。

特别是,整数值[低于尾数的位数]总是精确表示。

[显然,我们不知道calc对您的输入做了什么 - 这可能是任何和所有类型错误的来源,但我假设您实际上在询问{{1}在你建议的情况下,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更多的位

答案 1 :(得分:0)

没有。 y1的常量表达式隐式转换为doubley2的常量表达式已经是double

您在y3y4中正在做的是定义一个常量整数值并将其转换为double,此时您可以简单地将双精度浮点常量定义为你已经完成了。