How to produce formatting similar to .NET's '0.###%' in iostreams?
c++, iostream
Solution
I'm reasonably certain nothing built into iostreams supports this directly.
I think the cleanest way to handle it is to round the number before passing it to an iostream to be printed out:
#include <iostream>
#include <vector>
#include <cmath>
double rounded(double in, int places) {
double factor = std::pow(10, places);
return std::round(in * factor) / factor;
}
int main() {
std::vector<double> values{ 0.000000095123, 0.0095123, 0.95, 0.95123 };
for (auto i : values)
std::cout << "value = " << 100. * rounded(i, 5) << "%\n";
}
Due to the way it does rounding, this has a limitation on the magnitude of numbers it can work with. For percentages this probably isn't an issue, but if you were working with a number close to the largest that can be represented in the type in question (`double` in this case) the multiplication by `pow(10, places)` could/would overflow and produce bad results.
Though I can't be absolutely certain, it doesn't seem like this would be likely to cause an issue for the problem you seem to be trying to solve.
Problem
I would like to output a floating-point number as a percentage, with up to three decimal places. I know that iostreams have three different ways of presenting floats: "default", which displays using either the rules of `fixed` or `scientific`, depending on the number of significant digits desired as defined by `setprecision`; `fixed`, which displays a fixed number of decimal places defined by `setprecision`; and `scientific`, which displays a fixed number of decimal places but using scientific notation, i.e. mantissa + exponent of the radix. These three modes can be seen in effect with this code: ``` #include <iostream> #include <iomanip> int main() { double d = 0.00000095; double e = 0.95; std::cout << std::setprecision(3); std::cout.unsetf(std::ios::floatfield); std::cout << "d = " << (100. * d) << "%\n"; std::cout << "e = " << (100. * e) << "%\n"; std::cout << std::fixed; std::cout << "d = " << (100. * d) << "%\n"; std::cout << "e = " << (100. * e) << "%\n"; std::cout << std::scientific; std::cout << "d = " << (100. * d) << "%\n"; std::cout << "e = " << (100. * e) << "%\n"; } // output: // d = 9.5e-05% // e = 95% // d = 0.000% // e = 95.000% // d = 9.500e-05% // e = 9.500e+01% ``` None of these options satisfies me. I would like to avoid any scientific notation here as it makes the percentages really hard to read. I want to keep at most three decimal places, and it's ok if very small values show up as zero. However, I would also like to avoid trailing zeros in fractional places for cases like 0.95 above: I want that to display as in the second line, as "95%". In .NET, I can achieve this with a custom format string like "0.###%", which gives me a number formatted as a percentage with at least one digit left of the decimal separator, and up to three digits right of the decimal separator, trailing zeros skipped: http://ideone.com/uV3nDi Can I achieve this with iostreams, without writing my own formatting logic (e.g. special casing small numbers)?