將C++ float
變量的值爲0.6000002的變量截斷爲值0.6000並將其存儲回變量的最簡單方法是什麼?在C++中截斷十進制值
回答
首先知道浮點數是近似值是很重要的。請參閱@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);
實際上這是不可能的。這不是C++的限制,而只是浮點運算的方式。對於許多值沒有精確的表示,所以你不能簡單地截斷爲一些數字。
使用printf格式字符串打印時,可能會截斷。
如果您確實需要只能存儲有限數量的數字,我建議您改用固定精度的數據類型。
很好的參考爲什麼發生這種情況可以在David Goldberg的What Every Computer Scientist Should Know About Floating Point Arithmetic中找到。
我認爲這裏應該問的問題是: 爲什麼你需要它被截斷?
如果它用於比較值之間,也許你應該考慮使用epsilon測試。 (在你的情況下,額外的容差值,因爲它似乎遠遠大於普遍接受的epsilon)。
如果您只是想將其打印爲0.6000,請使用他人建議的方法。
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結果的地方,因爲你使用它的兩倍。)
由於如何花車通常儲存在電腦裏,有會可能是不準確的。不過,這就是你使用浮動的原因。
使用此:
floor(0.6000002*10000)/10000
下面是使用在其他的答案的建議和其使用的一個例子的功能:
#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);
}
到其他的答案相似,但你一定不要忘記圓,floor和trunc根據定義不同。請參見下面的定義和輸出例如:
http://www.cplusplus.com/reference/cmath/trunc/
在這種情況下,我們需要用4位小數精確到trucate,擺脫非顯著小數的:
trunc(valueToTrunc*10000)/10000
或
value = (double)((int)(valueToTrunc*10000))/(double)10000
對於C++ 11可以使用在標題<cmath>
定義std::round
:
auto trunc_value = std::round(value_to_trunc * 10000)/10000;
感謝張貼鏈接格雷格,我在寫我的答案時想到的確切文件,但不能爲我的生活記住標題。 – 2008-11-20 06:27:32