精度损失
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
将其解释为float
或double
,并且总是如此还是取决于某些编译器标志?如果它是一个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
。
您展示的任何替代方案都不会造成任何精度损失[至少如果编译器执行标准所说的应该做的事情,则不会]。也就是说,所有二元运算符,其中一个操作数是double
,另一端会自动提升为double
[通常,当两个操作数的大小不同时,它们被提升为较大的操作数]。
特别是,整数值[低于尾数的位数]总是精确表示。
[显然,我们不知道calc
如何处理您的输入 - 这可能是任何和各种错误的根源,但我假设您实际上是在问在您建议的情况下3.0/8.0
是否总是0.375
- 当然3/8
会导致零,因为这在两边都是整数]
针对正在编辑的原始问题进行编辑:
如果代码说1.
或1.0
或0.3
或.3
,则为double
。如果你写0.5f
,那就是float
。根据上述规则1.0/3
将是double(1.0)/double(3.0)
的结果。
从技术上讲,编译器可以只支持一种浮点类型,有 3 种不同的编写方式 - C 和 C++ 标准不要求double
比 float
多
No.y1
的常量表达式隐式转换为double
。y2
的常量表达式已经是一个double
。
你在y3
和y4
中所做的是定义一个常量整数值并将其转换为double
,此时您可以像已经做的那样简单地定义一个双精度浮点常量。
- 如何检测 std::vector::emplace_back 上的隐式转换损失整数精度
- int 到浮点转换的精度损失
- 将非常大的 int 转换为双倍,在某些计算机上会损失精度
- 在不损失精度的情况下将double从C++传输到python
- 禁止具有精度损失的整数转换
- 添加双精度时精度损失
- ceil、floor 和 round 在转换为整数时会遇到精度损失问题吗?
- 精度损失
- 精度损失(分配)
- 在C++中使用 pow 时精度损失
- 从浮子到双精度,从双精度到浮子的精度损失
- 将字符串转换为双精度,然后将双精度转换为字符串,而不会损失精度
- 处理在减去两个彼此接近的双精度时的精度损失
- 精度损失
- 在C++中将双精度转换为字符串时精度损失
- 在C++中标记双精度损失的算法不会标记正确的位置
- 如果可以接受一些精度损失,如何快速紧凑地保存双精度矩阵
- 编译器不会警告精度损失
- 这种精度损失发生在哪里以及如何防止
- 在 c++ 中将双精度转换为整数损失 1