0.6000002の値を持つC++float
変数を0.6000の値に切り捨てて、変数に格納する最も簡単な方法は何ですか?
10 に答える
これが発生する理由の良い参考資料は、DavidGoldbergによる浮動小数点演算についてすべてのコンピューター科学者が知っておくべきことです。
まず、浮動小数点数が概算されていることを知っておくことが重要です。この問題が完全に解決できない理由を理解するには、@GregHewgillが提供するリンクを参照してください。
しかし、おそらくあなたのニーズを満たすであろう問題に対するいくつかの解決策があります:
おそらくより良い方法ですが、効率は低くなります。
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形式の文字列を使用して印刷する場合は、切り捨てることができます。
本当に限られた桁数しか格納できない場合は、代わりに固定精度のデータ型を使用することをお勧めします。
ここで尋ねるべき質問は、なぜそれを切り捨てる必要があるのかということだと思います。
値を比較する場合は、イプシロンテストの使用を検討する必要があります。(あなたの場合、一般的に受け入れられているイプシロンよりもはるかに大きいように見えるので、追加の許容値があります)。
0.6000として印刷したいだけの場合は、他の人が提案した方法を使用してください。
roundf(myfloat * powf(10, numDigits)) / powf(10, numDigits);
たとえば、あなたの場合、3 桁 (numDigits) を切り捨てています。あなたが使用するだろう:
roundf(0.6000002 * 1000) / 1000
// And thus:
roundf(600.0002) / 1000
600 / 1000
0.6
(powf を 2 回使用しているので、おそらく powf の結果をどこかに保存するでしょう。)
フロートが通常コンピューターに保存される方法により、不正確になる可能性があります。ただし、フロートを使用することで得られるものです。
これを使って:
floor(0.6000002*10000)/10000
他の回答と同様に、しかし、ラウンド、フロア、およびトランクは定義上異なることを忘れてはなりません。次の定義と出力例を参照してください。
http://www.cplusplus.com/reference/cmath/trunc/
この場合、小数点以下 4 桁の精度で切り捨て、重要でない小数点を取り除く必要があります。
trunc(valueToTrunc*10000)/10000
また
value = (double)((int)(valueToTrunc*10000))/(double)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);
}