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
?
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
?
C++ inherits printf
from C. In C11 standard §7.21.6.1 The fprintf
function, the footnote says:
The results of all floating conversions of a negative zero, and of negative values that round to zero, include a minus sign.
The float representation ( https://en.wikipedia.org/wiki/Floating_point) has a sign bit. Who implemented the printf decided to explicitly put it there even when all the printed numbers are 0.
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.
EDIT: My previous solution didn't solve the problem as it should.
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");
}
Result: printf: -0.000 round : 0.000
Comparing printf w/ precision and round
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");
}
Result:
printf: 12345.68
printf: 12345.12
round : 12345.68
round : 12345.12
floor : 12345.67
floor : 12345.12
ceil : 12345.68
ceil : 12345.13
So printf seems to also round values when using precision.
You might use this to round your answer before printing it:
template <int precision>
double round(double a)
{
auto multiplier = std::pow(10, precision);
a *= multiplier;
a = std::round(a);
a /= multiplier;
return a;
}
Alternatively, if you just want to cut of the rest:
template <int precision>
double round_down(double a)
{
auto multiplier = std::pow(10, precision);
a *= multiplier;
a = std::floor(a);
a /= multiplier;
return a;
}
This works even with a negative precision:
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
}
Alternative solution, that allows defining the method of rounding:
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
}