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

这输出-0.000,但不应该0.000吗?

我怎样才能在没有减号的情况下进行打印,即0.000

4

4 回答 4

6

C++ 继承printf自 C。在 C11 标准§7.21.6.1 The fprintffunction中,脚注说:

负零的所有浮点转换以及四舍五入到零的负值的结果都包含一个减号。

于 2015-08-21T08:32:21.503 回答
1

浮点表示(https://en.wikipedia.org/wiki/Floating_point)有一个符号位。实现 printf 的人决定将其显式放在那里,即使所有打印的数字都是 0。

于 2015-08-21T08:34:46.967 回答
1

正确答案已经给出。只是想补充一点,您将从 c++ cout 中得到相同的结果

如果你想摆脱这个标志,可以这样做:

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;
}

输出:

-0.000
-0.000
0.000


编辑 这可以在不转换为字符串的情况下完成吗?

怎么样:

#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;
}

输出:

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

所以它似乎工作!

但它不适用于所有舍入模式。

因此,将第一个版本与字符串转换一起使用似乎更安全。

于 2015-08-21T08:53:16.313 回答
1

编辑:我以前的解决方案没有解决问题。

template <int precision=0, double(*round_func)(double)=std::round>
double round(double a)
{
    auto multiplier = std::pow(10, precision);
    a *= multiplier;
    a = round_func(a);
    if (a == 0.0) return 0.0;
    a /= multiplier;
    return a;
}

int main()
{
    printf("printf: %.3lf\n", -0.0001);
    printf("round : %.3lf\n", round<3>(-0.0001));
    system("PAUSE");
}

结果:printf:-0.000 回合:0.000

比较 printf 与精度和圆形

int main()
{
    printf("printf: %05.2lf\n", 12345.6789);                        
    printf("printf: %05.2lf\n", 12345.1234);                        
    printf("\n");
    printf("round : %05.2lf\n", round<2, std::round>(12345.6789));  
    printf("round : %05.2lf\n", round<2, std::round>(12345.1234));
    printf("\n");

    printf("floor : %05.2lf\n", round<2, std::floor>(12345.6789));  
    printf("floor : %05.2lf\n", round<2, std::floor>(12345.1234));
    printf("\n");

    printf("ceil  : %05.2lf\n", round<2, std::ceil>(12345.6789));   
    printf("ceil  : %05.2lf\n", round<2, std::ceil>(12345.1234));
    system("PAUSE");
}

结果:

printf: 12345.68
printf: 12345.12

round : 12345.68
round : 12345.12

floor : 12345.67
floor : 12345.12

ceil  : 12345.68
ceil  : 12345.13

所以 printf 在使用精度时似乎也会对值进行四舍五入。

--------------------------

旧答案,请忽略:

您可以在打印之前使用它来四舍五入您的答案:

template <int precision>
double round(double a)
{
    auto multiplier = std::pow(10, precision);
    a *= multiplier;
    a = std::round(a);
    a /= multiplier;
    return a;
}

或者,如果您只想删除其余部分:

template <int precision>
double round_down(double a)
{
    auto multiplier = std::pow(10, precision);
    a *= multiplier;
    a = std::floor(a);
    a /= multiplier;
    return a;
}

这即使在负精度下也有效:

int main()
{
    //Round at precision
    printf("%5.4lf\n", round<4>(12345.6789));           //Output = 12345.6789
    printf("%5.4lf\n", round<3>(12345.6789));           //Output = 12345.6790
    printf("%5.4lf\n", round<2>(12345.6789));           //Output = 12345.6800
    printf("%5.4lf\n", round<1>(12345.6789));           //Output = 12345.7000
    printf("%5.4lf\n", round<0>(12345.6789));           //Output = 12346.0000
    printf("%5.4lf\n", round<-1>(12345.6789));          //Output = 12350.0000
    printf("%5.4lf\n", round<-2>(12345.6789));          //Output = 12300.0000
    printf("%5.4lf\n", round<-3>(12345.6789));          //Output = 12000.0000
    printf("%5.4lf\n", round<-4>(12345.6789));          //Output = 10000.0000
    printf("%5.4lf\n", round<-5>(12345.6789));          //Output = 0.0000

    //Cut off/Round down after precision
    printf("%5.4lf\n", round_down<4>(12345.6789));      //Output = 12345.6789
    printf("%5.4lf\n", round_down<3>(12345.6789));      //Output = 12345.6780
    printf("%5.4lf\n", round_down<2>(12345.6789));      //Output = 12345.6700
    printf("%5.4lf\n", round_down<1>(12345.6789));      //Output = 12345.6000
    printf("%5.4lf\n", round_down<0>(12345.6789));      //Output = 12345.0000
    printf("%5.4lf\n", round_down<-1>(12345.6789));     //Output = 12340.0000
    printf("%5.4lf\n", round_down<-2>(12345.6789));     //Output = 12300.0000
    printf("%5.4lf\n", round_down<-3>(12345.6789));     //Output = 12000.0000
    printf("%5.4lf\n", round_down<-4>(12345.6789));     //Output = 10000.0000
    printf("%5.4lf\n", round_down<-5>(12345.6789));     //Output = 0.0000
}

替代解决方案,允许定义舍入方法:

template <int precision=0, double(*round_func)(double)=std::round>
double round(double a)
{
    auto multiplier = std::pow(10, precision);
    a *= multiplier;
    a = round_func(a);
    a /= multiplier;
    return a;
}

int main()
{
    printf("%05.4lf\n", round(12345.6789));                     //Output = 12345.0000
    printf("%05.4lf\n", round<1>(12345.6789));                  //Output = 12345.7000
    printf("%05.4lf\n", round<1, std::round>(12345.6789));      //Output = 12345.7000
    printf("%05.4lf\n", round<1, std::floor>(12345.6789));      //Output = 12345.6000
    printf("%05.4lf\n", round<1, std::ceil>(12345.6789));       //Output = 12345.7000
}
于 2015-08-21T09:33:34.560 回答