10

Java で浮動小数点値を処理する場合、このtoString()メソッドを呼び出すと、浮動小数点の有効数字の数が正しい値が出力されます。ただし、C++ では、float ビアを出力stringstreamすると、値が 5 桁以下で丸められます。C++ の浮動小数点数を (想定される) 有効数字の正しい数に "きれいに印刷" する方法はありますか?


編集:誤解されていると思います。出力を固定精度ではなく、動的な長さにしたい。私はsetprecisionに精通しています。Double の Java ソースを見ると、何らかの方法で有効桁数が計算されます。それがどのように機能するか、および/またはこれを C++ で簡単に複製することがどれほど実現可能かを理解したいと思います。

/*
 * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
 */
public FloatingDecimal( double d )
{
    long    dBits = Double.doubleToLongBits( d );
    long    fractBits;
    int     binExp;
    int     nSignificantBits;

    // discover and delete sign
    if ( (dBits&signMask) != 0 ){
        isNegative = true;
        dBits ^= signMask;
    } else {
        isNegative = false;
    }
    // Begin to unpack
    // Discover obvious special cases of NaN and Infinity.
    binExp = (int)( (dBits&expMask) >> expShift );
    fractBits = dBits&fractMask;
    if ( binExp == (int)(expMask>>expShift) ) {
        isExceptional = true;
        if ( fractBits == 0L ){
            digits =  infinity;
        } else {
            digits = notANumber;
            isNegative = false; // NaN has no sign!
        }
        nDigits = digits.length;
        return;
    }
    isExceptional = false;
    // Finish unpacking
    // Normalize denormalized numbers.
    // Insert assumed high-order bit for normalized numbers.
    // Subtract exponent bias.
    if ( binExp == 0 ){
        if ( fractBits == 0L ){
            // not a denorm, just a 0!
            decExponent = 0;
            digits = zero;
            nDigits = 1;
            return;
        }
        while ( (fractBits&fractHOB) == 0L ){
            fractBits <<= 1;
            binExp -= 1;
        }
        nSignificantBits = expShift + binExp +1; // recall binExp is  - shift count.
        binExp += 1;
    } else {
        fractBits |= fractHOB;
        nSignificantBits = expShift+1;
    }
    binExp -= expBias;
    // call the routine that actually does all the hard work.
    dtoa( binExp, fractBits, nSignificantBits );
}

この関数の後、dtoa( binExp, fractBits, nSignificantBits );一連のケースを処理する呼び出しが行われます - これは OpenJDK6 からのものです


より明確にするために、例: Java:

double test1 = 1.2593;
double test2 = 0.004963;
double test3 = 1.55558742563;
    
System.out.println(test1);
System.out.println(test2);
System.out.println(test3);

出力:

1.2593
0.004963
1.55558742563

C++:

std::cout << test1 << "\n";
std::cout << test2 << "\n";
std::cout << test3 << "\n";

出力:

1.2593
0.004963
1.55559
4

4 に答える 4

6

正確に同じ浮動小数点数を読み取ることができる浮動小数点数の最小数を出力する方法について話していると思います。この論文は、このトリッキーな問題への良い入門書です。

http://grouper.ieee.org/groups/754/email/pdfq3pavhBfih.pdf

dtoa 関数は David Gay の作品のように見えます。ソースはhttp://www.netlib.org/fp/dtoa.cにあります(ただし、これは Java ではなく C です)。

ゲイはまた、彼の方法について論文を書きました。リンクはありませんが、上記の論文で参照されているので、おそらくグーグルで検索できます。

于 2012-07-27T22:02:42.863 に答える
-1

必要な桁数を指定できるios_base::precisionテクニックを使用できます

例えば

#include <iostream>
using namespace std;

int main () {
double f = 3.14159;
cout.unsetf(ios::floatfield);            // floatfield not set
cout.precision(5);
cout << f << endl;
cout.precision(10);
cout << f << endl;
cout.setf(ios::fixed,ios::floatfield);   // floatfield set to fixed
cout << f << endl;
return 0;

上記のコード と 出力
3.14163.141593.1415900000


于 2012-07-27T20:35:46.560 に答える
-1

numeric_limits というユーティリティがあります。

#include <limits>

    ...
    int num10 = std::numeric_limits<double>::digits10;
    int max_num10 = std::numeric_limits<double>::max_digits10;

IEEE 番号は 10 進数で正確に表されないことに注意してください。これらはバイナリ量です。より正確な数値は、バイナリ ビットの数です。

    int bits = std::numeric_limits<double>::digits;

すべての有効桁数をきれいに出力するには、次のように setprecision を使用します。

out.setprecision(std::numeric_limits<double>::digits10);
于 2012-07-27T22:30:10.253 に答える