10

将值为 0.6000002的 C++float变量截断为值为 0.6000 并将其存储回变量中的最简单方法是什么?

4

10 回答 10

12

关于为什么会发生这种情况的一个很好的参考可以在David Goldberg的What Every Computer Scientist Should Know About Floating Point Arithmetic中找到。

于 2008-11-20T00:57:09.970 回答
9

首先,重要的是要知道浮点数是近似的。请参阅@Greg Hewgill 提供的链接,了解为什么这个问题无法完全解决。

但这里有几个可能会满足您需求的问题的解决方案:

可能是更好的方法,但效率较低:

char sz[64];
double lf = 0.600000002;
sprintf(sz, "%.4lf\n", lf); //sz contains 0.6000

double lf2 = atof(sz);

//lf == 0.600000002;
//lf2 == 0.6000

printf("%.4lf", lf2); //print 0.6000

更有效的方法,但可能不太精确:

double lf = 0.600000002;
int iSigned = lf > 0? 1: -1;
unsigned int uiTemp = (lf*pow(10, 4)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate
lf = (((double)uiTemp)/pow(10,4) * iSigned);
于 2008-11-20T00:49:53.153 回答
7

实际上这是不可能的。这不是 C++ 的限制,而是浮点的工作方式。对于许多值,没有精确的表示,因此您不能简单地截断为多个数字。

使用 printf 格式字符串打印时可以截断。

如果您确实需要能够仅存储有限数量的数字,我建议您改用固定精度数据类型。

于 2008-11-20T00:53:54.843 回答
4

我认为这里应该问的问题是:为什么需要截断它?

如果它用于值之间的比较,也许您应该考虑使用 epsilon 测试。(在您的情况下,具有额外的容差值,因为它似乎远大于普遍接受的 epsilon)。

如果您只想将其打印为 0.6000 ,请使用其他人建议的方法。

于 2008-11-20T02:07:54.133 回答
2
roundf(myfloat * powf(10, numDigits)) / powf(10, numDigits);

例如,在您的情况下,您要截断三位数(numDigits)。你会使用:

roundf(0.6000002 * 1000) / 1000
// And thus:
roundf(600.0002) / 1000
600 / 1000
0.6

(您可能会将 powf 的结果存储在某处,因为您使用了两次。)

由于浮点数通常存储在计算机上的方式,可能会有不准确之处。不过,这就是使用浮点数所得到的。

于 2008-11-23T02:13:31.843 回答
2

用这个:

floor(0.6000002*10000)/10000
于 2010-02-07T04:21:34.770 回答
1

与其他答案类似,但您不能忘记 round、floor 和 trunc 在定义上是不同的。请参阅以下定义和输出示例:

http://www.cplusplus.com/reference/cmath/trunc/

在这种情况下,我们需要以 4 位小数的精度进行 trucate 并去掉不重要的小数:

trunc(valueToTrunc*10000)/10000

或者

value = (double)((int)(valueToTrunc*10000))/(double)10000
于 2016-01-20T18:58:17.033 回答
1

对于 C++11,您可以使用std::round在 header 中定义<cmath>

auto trunc_value = std::round(value_to_trunc * 10000) / 10000;
于 2017-04-28T19:04:19.803 回答
0

这是一个使用其他答案中的建议的函数及其使用示例:

#include <iostream>
#include <cmath>

static void Truncate(double& d, unsigned int numberOfDecimalsToKeep);

int main(int, char*[])
{

  double a = 1.23456789;
  unsigned int numDigits = 3;

  std::cout << a << std::endl;

  Truncate(a,3);

  std::cout << a << std::endl;

  return 0;
}

void Truncate(double& d, unsigned int numberOfDecimalsToKeep)
{
    d = roundf(d * powf(10, numberOfDecimalsToKeep)) / powf(10, numberOfDecimalsToKeep);
}
于 2013-03-14T16:33:39.170 回答
0

你可以使用这个:

int n = 1.12378;
cout << fixed << setprecision(4) << n;

输出将是:1.1238

不是:1.1237

它只是海最后一个十进制数字不是全部:12.123447 ==> 12.1234

小心那个...

于 2020-12-03T11:50:13.723 回答