我的功能如下:
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
来保证安全。
答案 0 :(得分:3)
您展示的任何替代方案都不会导致任何精度损失[至少在编译器执行标准应该执行的操作时不会这样做]。这是所有二元运算符,其中一个操作数是double
,另一方自动升级为double
[并且通常,当两个操作数大小不同时,它们被提升为更大的操作数]。
特别是,整数值[低于尾数的位数]总是精确表示。
[显然,我们不知道calc
对您的输入做了什么 - 这可能是任何和所有类型错误的来源,但我假设您实际上在询问{{1}在你建议的情况下,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
更多的位
答案 1 :(得分:0)
没有。 y1
的常量表达式隐式转换为double
。 y2
的常量表达式已经是double
。
您在y3
和y4
中正在做的是定义一个常量整数值并将其转换为double
,此时您可以简单地将双精度浮点常量定义为你已经完成了。