浮点到双精度转换的舍入误差
float rounding error float to double conversion
我有一个系统,我现在不能改变,是使用浮动存储信息。
我有一个舍入误差的问题。例子:
std::string floatToStr(float d)
{
std::stringstream ss;
ss << std::fixed << std::setprecision(15) << d;
return ss.str();
}
float val723 = 0.575f;
std::cout << floatToStr(val723) << std::endl;
结果
0.574999988079071
我可以用字符串处理来纠正这个问题。
std::string doubleToStr(double d, int precision)
{
std::stringstream ss;
ss << std::fixed << std::setprecision(precision) << d;
return ss.str();
}
double val945 = (double)0.575f;
std::cout << doubleToStr(atof(doubleToStr(val945, 4).c_str()), 15) << std::endl;
结果是:
0.575000000000000
但这是一个昂贵的解决方案。有没有更好的解决方案可以在实时过程中使用?(实际上我不需要在我的实时代码中使用它,但我准备好了,如果我必须在实时代码中使用它。)
Edit1:我知道我可以使用小数点后的6或7位数字浮点类型。
您可以用代码打破。PC的工作方式是二进制,而0.575是一个必须近似的小数。
正确的解决方案是将浮点数打印为不超过其物理存储的数字(7),并打印其真实值,而不是您认为它应该包含的十进制值。
你要的是小数点后15位,这就是它给你的。抱怨这个似乎有点矛盾!
该值是浮点数,这意味着6个十进制数字是可用精度的极限(如果您确信几乎没有舍入误差,则为7)。要求15位小数,后面的。'显示浮点数的ls位的状态,它会受到舍入和表示错误的影响。
您似乎想要做的是将浮点数的值呈现为双精度,即小数的15位,然后您需要将浮点数的双精度版本四舍五入到6(或者,如果您觉得勇敢的话)7 小数位的精度。这与二进制到十进制的转换非常相似,但您需要准备值的双副本,以便输出。
这与将值的字符串版本转换为6位数并将其转换为双精度值相差不远。你可以为自己建立更快!
不幸的是,仍然存在一个问题。您要求在 '.'后面输入15位小数。这将显示大于10.0的值以及介于1.0和10.00之间的值的表示错误。例如:如果你的浮点值是(比如说)57.51234f(其实际值大约是57.512340545654297);下面的代码将提供575124.0/10000.0作为双精度数,当输出时得到:57.512300000000003——因为您要求的是比双精度数多出大约1位的数字。(对于5751.234f,同样的过程给出5751.229999999999563.)
我会仔细考虑为什么'后面有15个小数。'是必需的,特别是当数据只有6-7位总精度时——所以在大多数中,'之后的6-7位"好"数字。',取决于数字的大小。
顺带一提:你可以把数字转换成科学形式,然后直接处理字符串——这是下面代码所做的另一种方式。
double pt[] = { 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9,
1E10, 1E11, 1E12, 1E13, 1E14, 1E15, 1E16, 1E17, 1E18, 1E19 } ;
double xx ;
int de ;
de = 6 - (int)ceilf(log10f(x)) ; /* where 'x' is the float to be shown */
if ((de > 15) || (de < -18)) /* de > 15 -- no need to round, value too small */
/* de < 18 -- cannot round, value too big */
xx = x ; /* xx is value to output */
else
{
while (1)
{
xx = x ;
if (de < 0)
xx /= pt[-de] ;
else if (de > 0)
xx *= pt[+de] ;
xx = round(xx) ;
if (xx < pt[5])
de += 1 ;
else if (xx > pt[6])
de -= 1 ;
else
break ;
} ;
if (de < 0)
xx *= pt[-de] ;
else if (de > 0)
xx /= pt[+de] ;
} ;
ss << std::fixed << std::setprecision(15) << xx ;
- 将大 int 转换为浮点数,而不舍入 c++
- 避免将 Int 转换为双重类型转换舍入
- 类型转换<int>的舍入问题
- 定义范围,尽管C++舍入误差
- 舍入误差在DFT中给出不正确的tesult
- 如何在 +、-、* 和 / 中舍入误差后计算浮点精度
- 将浮点数转换为整数时如何舍入
- 在C++中使用地板函数的舍入误差
- 将长双精度转换为向上(或向下)舍入的双精度
- 将正浮点数组转换为无符号短数组,并按C++舍入
- 将浮点转换为无符号短整型时出现舍入问题
- 浮点到双精度转换的舍入误差
- c++ linux x86_64中如何控制双精度计算以避免舍入误差
- R舍入误差与c++舍入误差
- "floor"是否有可能由于浮点舍入误差而返回不准确的结果?
- 射线平面相交:不准确的结果-舍入误差
- 浮点舍入误差
- C++、点和线在2D中的位置对舍入误差和位置具有鲁棒性
- C++中的舍入误差
- std::cbrt的舍入误差