精度损失?

Loss of 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 标志编译的,你 do 会失去精度。

#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

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

你在 y3y4 中所做的是定义一个常量整数值并将其转换为 double,而你可以简单地定义一个双精度浮点数正如您所做的那样保持不变。

None 您显示的替代方案会导致任何精度损失 [至少如果编译器按照标准所说的去做,则不会]。即所有一个操作数是 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.