Search code examples
c++printfdoubledouble-precisionnegative-zero

Can I print -0.000 as 0.000?


printf("%.3lf\n", -0.0001);

This outputs -0.000, but shouldn't it be 0.000?

How can I make this print without the minus sign, i.e. 0.000 ?


Solution

  • The correct answer has already been given. Just wanted to add that you'll get the same from c++ cout

    If you want to get rid of the sign, it can be done like this:

    double fixSign(double d)
    {
        std::ostringstream strs;
        strs << std::fixed << std::setprecision(3) << d;
        std::string str = strs.str();
    
        if (str == "-0.000") return 0.0;
    
        return d;
    }
    
    int main()
    {
        double d=-0.0001;
    
        printf("%.3lf\n", d);
    
        cout << std::fixed << std::setprecision(3) << d << endl;
    
        cout << std::fixed << std::setprecision(3) << fixSign(d) << endl;
    
        return 0;
    }
    

    output:

    -0.000
    -0.000
    0.000
    


    EDIT Could this be done without converting to string?

    How about:

    #define PRE 3
    #define LIMIT -0.0005  // Must have PRE zeros after the decimal point
    
    // VERSION WITHOUT USE OF STRING
    double fixSign_v2(double d)
    {
        if ((d < 0) && (d > LIMIT)) return 0;
    
        return d;
    }
    
    double fixSign(double d)
    {
        std::ostringstream strs;
        strs << std::fixed << std::setprecision(PRE) << d;
        std::string str = strs.str();
    
        if (str == "-0.000") return 0.0;
    
        return d;
    }
    
    int main()
    {
        // PRE == 2
        //double d1=-0.005;
        //double d2=-0.0049999999999;
    
        // PRE == 3
        double d1=-0.0005;
        double d2=-0.000499999999999;
    
        // PRE == 10
        //double d1=-0.00000000005;
        //double d2=-0.0000000000499999999;
    
        cout << std::fixed << std::setprecision(PRE+20) << d1 << endl;
    
        cout << std::fixed << std::setprecision(PRE) << fixSign(d1) << endl;
    
        cout << std::fixed << std::setprecision(PRE) << fixSign_v2(d1) << endl;
    
        cout << "------------------------" << endl;
    
        cout << std::fixed << std::setprecision(PRE) << d2 << endl;
    
        cout << std::fixed << std::setprecision(PRE) << fixSign(d2) << endl;
    
        cout << std::fixed << std::setprecision(PRE) << fixSign_v2(d2) << endl;
    
        return 0;
    }
    

    output:

    -0.001
    -0.001
    -0.001
    ------------------------
    -0.000
    0.000
    0.000
    

    so it seems to work!

    But it won't work for all rounding modes.

    Therefore it seems safer to use the first version with string convert.