如何计算c ++ double的有效小数位数?

dav*_*ave 8 c++ floating-point precision string-formatting

在Java中处理浮点值时,调用toString()方法会给出一个打印值,该值具有正确的浮点数有效数字.但是,在C++中,通过stringstream打印float会在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 );
}
Run Code Online (Sandbox Code Playgroud)

在这个函数之后,它调用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);
Run Code Online (Sandbox Code Playgroud)

输出:

1.2593
0.004963
1.55558742563
Run Code Online (Sandbox Code Playgroud)

C++:

std::cout << test1 << "\n";
std::cout << test2 << "\n";
std::cout << test3 << "\n";
Run Code Online (Sandbox Code Playgroud)

输出:

1.2593
0.004963
1.55559
Run Code Online (Sandbox Code Playgroud)

jah*_*haj 5

我想你正在讨论如何打印最小数量的浮点数,这些数字允许你读回完全相同的浮点数.本文是对这个棘手问题的一个很好的介绍.

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

dtoa函数看起来像David Gay的工作,你可以在http://www.netlib.org/fp/dtoa.c找到源代码(虽然这是C而不是Java).

盖伊还写了一篇关于他的方法的论文.我没有链接,但它在上面的论文中引用,所以你可以谷歌它.