在 C++ 中截断十进制值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/304011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Truncate a decimal value in C++
提问by BeachRunnerFred
What's the easiest way to truncate a C++ float
variable that has a value of 0.6000002 to a value of 0.6000 and store it back in the variable?
float
将值为 0.6000002的 C++变量截断为 0.6000 并将其存储回变量中的最简单方法是什么?
采纳答案by Brian R. Bondy
First it is important to know that floating point numbers are approximated. See the link provided by @Greg Hewgill to understand why this problem is not fully solvable.
首先,重要的是要知道浮点数是近似的。请参阅@Greg Hewgill 提供的链接以了解为什么此问题无法完全解决。
But here are a couple of solutions to the problem that will probably meet your need:
但这里有一些解决问题的方法可能会满足您的需求:
Probably the better method but less efficient:
可能是更好的方法,但效率较低:
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
The more efficient way, but probably less precise:
更有效的方法,但可能不太精确:
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);
回答by Greg Hewgill
A good reference for whythis happens can be found in What Every Computer Scientist Should Know About Floating Point Arithmeticby David Goldberg.
关于为什么会发生这种情况的一个很好的参考可以在David Goldberg 的What Every Computer Scientist should Know About Floating Point Arithmetic 中找到。
回答by Kamil Kisiel
Realistically that's not possible. It's not a C++ limitation, but just the way floating point works. For many values there are no precise representations, so you can't simply truncate to a number of digits.
实际上这是不可能的。这不是 C++ 的限制,而只是浮点数的工作方式。对于许多值,没有精确的表示,因此您不能简单地截断为多个数字。
You could truncate when printing using printf format strings.
使用 printf 格式字符串打印时可以截断。
If you really need to be able to store only a limited number of digits, I suggest you use a fixed-precision data type instead.
如果您真的只需要能够存储有限数量的数字,我建议您改用固定精度数据类型。
回答by Alex Lim
i think the question that should be asked here is: Why do you need it truncated?
我认为这里应该问的问题是:为什么需要截断它?
If its for comparison between values, perhaps you should consider using the epsilon test. (with an extra tolerance value, in your case, since it seems to be far larger than the generally accepted epsilon).
如果它用于值之间的比较,也许您应该考虑使用 epsilon 测试。(在您的情况下,有一个额外的容差值,因为它似乎远大于普遍接受的 epsilon)。
If you're just wanting to print it out as 0.6000 , use the methods others have suggested.
如果您只想将其打印为 0.6000 ,请使用其他人建议的方法。
回答by strager
roundf(myfloat * powf(10, numDigits)) / powf(10, numDigits);
For example, in your case you're truncating three digits (numDigits). You'd use:
例如,在您的情况下,您要截断三位数 (numDigits)。你会使用:
roundf(0.6000002 * 1000) / 1000
// And thus:
roundf(600.0002) / 1000
600 / 1000
0.6
(You'd probably store the result of powf somewhere, since you're using it twice.)
(您可能会将 powf 的结果存储在某处,因为您使用了两次。)
Due to how floats are normally stored on computers, there'd probably be inaccuracies. That's what you get for using floats, though.
由于浮点数通常存储在计算机上的方式,可能存在不准确之处。不过,这就是使用浮点数所得到的结果。
回答by JBOI
Use this:
用这个:
floor(0.6000002*10000)/10000
回答by chema989
For C++11 you can use std::round
defined in header <cmath>
:
对于 C++11,您可以std::round
在 header 中使用定义<cmath>
:
auto trunc_value = std::round(value_to_trunc * 10000) / 10000;
回答by David Doria
Here is a function using the advice in other answers and an example of its use:
这是一个使用其他答案中的建议的函数及其使用示例:
#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);
}
回答by Rubarb
Similar to other answers, BUT you must not forget that round, floor and trunc are different by definition. See the definition and output example of the following:
与其他答案类似,但您一定不要忘记 round、floor 和 trunc 在定义上是不同的。请参阅以下内容的定义和输出示例:
http://www.cplusplus.com/reference/cmath/trunc/
http://www.cplusplus.com/reference/cmath/trunc/
In this case we need to trucate with a precision of 4 decimals and get rid of non-significant decimals:
在这种情况下,我们需要以 4 位小数的精度截断并去除无意义的小数:
trunc(valueToTrunc*10000)/10000
or
或者
value = (double)((int)(valueToTrunc*10000))/(double)10000