iomanip set at most 4 digits after decimal point - c++

I want to print to screen some numbers with at most 4 digits after decimal point using iomanip.
I've learned that in default mode setprecision counts not only the digits after decimal point but also the digits in the integer part. This code
#include <iostream>
#include <iomanip>
int main () {
double numbers[] = {3.141516, 1.01, 200.78901, 0.12345};
int len = sizeof(numbers) / sizeof(numbers[0]);
std::cout << std::setprecision(4);
for (int i = 0; i < len; ++i) {
std::cout << numbers[i] << '\n';
}
return 0;
}
outputs:
3.142
1.01
200.8
0.1235
But what I want is: (at most 4 digits after decimal point without trailing zeros)
3.1415
1.01
200.789
0.1235
Is iomanip capable of doing this? Without using other tricks (like round)?
EDIT
It seems that I haven't made it clear enough. My question is iomanip specific
All I want to know is whether iomanip is capable of doing things I've described because iomanip is said to be the standard library for input/output manipulators. The posted question is
Is iomanip capable of doing this?
It's more like "is it supported" rather than "give me any solution".
I have searched it again, looked up iomanip references hoping for a clean and compact way to format floating numbers for at most n digits, using unnecessary libraries as little as possible.
And there seems to be no standard way to achieve this.

One (ugly) option to obtain OP's desired output is to represent the number with the wanted maximum precision and then just remove the unwanted zeroes:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
int main()
{
std::vector<double> numbers {
3.141516, 1.01, 200.78901, 0.12345, 9.99999
};
for (auto x : numbers)
{
// "print" the number
std::stringstream ss;
ss << std::fixed << std::setprecision(4) << x;
// remove the unwanted zeroes
std::string result{ss.str()};
while (result.back() == '0')
result.pop_back();
// remove the separator if needed
if (result.back() == '.')
result.pop_back();
std::cout << result << '\n';
}
std::cout << "\nJustified:\n";
for (auto x : numbers)
{
// "print" the number
std::stringstream ss;
ss << std::fixed << std::setprecision(4) << std::setw(15) << x;
// remove the unwanted zeroes
std::string result{ss.str()};
auto it = result.rbegin();
while (*it == '0')
*it++ = ' ';
// remove the separator if needed
if (*it == '.')
*it = ' ';
std::cout << result << '\n';
}
}
Live example: https://ideone.com/8zP17O

So:
in std::fixedfield mode, std::setprecision sets the maximum number of significant figures, not decimal places;
if you flip to std::fixed it means exact number of decimal places;
C++ does not provide any analogue to the %.Nf printf format string! (up to N decimal places)
I've just thrown together a little fake I/O manipulator that can get the behaviour we both want. It's not terribly performant, but it does the job:
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cstdio>
struct sprintf_wrapper
{
sprintf_wrapper(std::string fmt_str)
: _fmt_str(std::move(fmt_str))
{}
struct proxy
{
proxy(const sprintf_wrapper& wrapper, std::ostream& os)
: _wrapper(wrapper)
, _os(os)
{}
std::ostream& Resolve(const double value) const
{
// First find out how many characters we're going to need
const int len = std::snprintf(nullptr, 0, _wrapper._fmt_str.c_str(), value);
if (len < 0)
{
_os.setstate(std::ios::failbit);
return _os;
}
// Then allocate a buffer
std::string result;
result.resize(len);
// Actually serialise the value according to the format string
if (std::sprintf(result.data(), _wrapper._fmt_str.c_str(), value) < 0)
{
_os.setstate(std::ios::failbit);
return _os;
}
// Stream it out
_os.write(result.data(), result.size());
return _os;
}
friend std::ostream& operator<<(const proxy& obj, const double val)
{
return obj.Resolve(val);
}
private:
const sprintf_wrapper& _wrapper;
std::ostream& _os;
};
friend proxy operator<<(std::ostream& os, const sprintf_wrapper& obj)
{
return proxy(obj, os);
}
private:
std::string _fmt_str;
};
inline auto sprintf_f(size_t n, const bool showpos = false)
{
std::stringstream fmt;
fmt << '%';
if (showpos) fmt << '+';
fmt << '.' << n << 'f';
return sprintf_wrapper(fmt.str());
}
int main()
{
std::cout << sprintf_f(2) << 4.123456789 << '\n';
std::cout << sprintf_f(3) << 4.123456789 << '\n';
std::cout << sprintf_f(4) << 4.123456789 << '\n';
std::cout << sprintf_f(5) << 4.123456789 << '\n';
std::cout << sprintf_f(6) << 4.123456789 << '\n';
}
(live demo)

Use a combination of std::fixed and std::setprecision.
#include <iomanip>
#include <iostream>
int main() {
double d = 311.3456;
std::cout << std::fixed;
std::cout << std::setprecision(4);
std::cout << d << std::endl;
}

Related

How to remove trailing zeros with scientific notation when convert double to string?

Live On Coliru
FormatFloat
I try to implement one conversion of Golang strconv.FormatFloat() in C++.
#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
std::string convert_str(double d)
{
std::stringstream ss;
if (d >= 0.0001)
{
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else
{
ss << std::scientific;
ss << d;
return ss.str();
}
}
int main()
{
std::cout << convert_str(0.002) << std::endl; // 0.0020
std::cout << convert_str(0.00001234560000) << std::endl; // 1.234560e-05
std::cout << convert_str(0.000012) << std::endl; // 1.200000e-05
return 0;
}
Output:
0.0020
1.234560e-05 // should be 1.23456e-05
1.200000e-05 // should be 1.2e-05
Question> How can I setup the output modifier so that the trailing zero doesn't show up?
strconv.FormatFloat(num, 'e', -1, 64)
The special precision value (-1) is used for the smallest number of
digits necessary such that ParseFloat() will return f exactly.
At the risk of being heavily downvoted criticised for posting a C answer to a C++ question ... you can use the %lg format specifier in a call to sprintf.
From cpprefernce:
Unless alternative representation is requested the trailing zeros are
removed, also the decimal point character is removed if no fractional
part is left.
So, if you only want to remove the trailing zeros when using scientific notation, you can change your convert_str function to something like the following:
std::string convert_str(double d)
{
if (d >= 0.0001) {
std::stringstream ss;
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else {
char cb[64];
sprintf(cb, "%lg", d);
return cb;
}
}
For the three test cases in your code, this will give:
0.0020
1.23456e-05
1.2e-05
From C++20 and later, the std::format class may offer a more modern alternative; however, I'm not (yet) fully "up to speed" with that, so I cannot present a solution using it. Others may want to do so.
Yes, std::scientific don't remove trailing zeros from scientific notation. The good news, for your specific case, is that cout already format values below 0.0001 using scientific notation, and removing trailing zeros. So you can let your code like this:
#include <sstream>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
std::string convert_str(double d)
{
std::stringstream ss;
if (d >= 0.0001)
{
ss << std::fixed << std::setprecision(4); // I know the precision, so this is fine
ss << d;
return ss.str();
}
else
{
ss << d;
return ss.str();
}
}
int main()
{
std::cout << convert_str(0.002) << std::endl; // 0.0020
std::cout << convert_str(0.00001234560000) << std::endl; // 1.23456e-05
std::cout << convert_str(0.000012) << std::endl; // 1.2e-05
return 0;
}
The wanted output can be generated with a combination of the std::setprecision and std::defaultfloat manipulators:
std::cout << std::setprecision(16) << std::defaultfloat
<< 0.002 << '\n'
<< 0.00001234560000 << '\n'
<< 0.000012 << '\n';
Live at: https://godbolt.org/z/67fWa1seo

ios_base::fixed & truncating trailing zeroes

When printing certain decimal numbers, rounding may occur (my present platform is the IBM iSeries). If I set ios_base::fixed, it does better but prints annoying trailing (and insignificant) zeroes. Anyone have a better way? For the platform I'm using, the output is this:
myval=100000
myval=99999.990000
myval as string =99999.990000
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <unistd.h>
#include <algorithm>
using namespace std;
// returns t
template<typename T> string toString(const T& val)
{
stringstream os;
os.setf(std::ios_base::fixed);
os << val;
return os.str();
}
class MyApp {
private :
public :
MyApp();
virtual ~MyApp();
void run();
operator bool() const { return true; }
};
MyApp::MyApp()
{
}
MyApp::~MyApp()
{
}
void MyApp::run()
{
double myval = 99999.99;
string myval_as_string = toString<double>(myval);
cout << "myval=" << myval << endl;
cout.setf(std::ios_base::fixed);
cout << "myval=" << myval << endl;
cout << "myval as string =" << myval_as_string << endl;
}
int main(int argc, char* argv[])
{
MyApp myApp;
myApp.run();
}
You're looking for precision and not fixed. precision will specify the maximum precision used but it will not automatically print more zeros so increase it as much as you need. fixed will force it out to as many zeros as precision is set to. If you have set fixed previously, you can reset it with ios_base::defaultfloat.
template<typename T> string toString(const T& val)
{
stringstream os;
os.precision(15);
os << val;
return os.str();
}
....
void MyApp::run()
{
double myval = 99999.99;
string myval_as_string = toString<double>(myval);
cout << "myval=" << myval << endl;
cout.precision(15);
cout << "myval=" << myval << endl;
cout << "myval as string =" << myval_as_string << endl;
}
For more info, you can check out the standard here: http://www.cplusplus.com/reference/ios/ios_base/precision/. Note the following line:
Using the default floating-point notation, the precision field
specifies the maximum number of meaningful digits to display in total
counting both those before and those after the decimal point. Notice
that it is not a minimum, and therefore it does not pad the displayed
number with trailing zeros if the number can be displayed with less
digits than the precision.

C++ how to avoid trailing zeroes?

If you do
double number;
cout.precision(3)
cout<<number;
for a number like 1.23456 you get 1.234 but if the number is 1.2 you get 1.200. How to get both 1.234 and 1.2 (they are useless zeroes)? Suppose you don't know what number you have to print.
#include <iostream>
#include <iomanip>
using namespace std;
auto main() -> int
{
cout << setprecision( 4 );
cout << 1.23456 << endl; // -> "1.235"
cout << 1.2 << endl; // -> "1.2"
}
It's that simple: it's what you get by default.
C++03 lacked a manipulator for resetting to default formatting after setting fixed or scientific. However, in C++11 the defaultfloat manipulator was introduced. You can use it like this:
#include <iostream> // defaultfloat
#include <iomanip> // setprecision
using namespace std;
#ifdef __GNUC__ // Also check for version number, e.g. 4.8.2 and earlier
namespace std {
inline
auto defaultfloat( ios_base& stream )
-> ios_base&
{ stream.unsetf( ios_base::floatfield ); return stream; }
}
#endif
auto main() -> int
{
cout << "Lots of digits: " << fixed << setprecision( 16 ) << 1.2 << endl;
cout << endl;
cout << "Deault presentation:" << endl;
cout << defaultfloat;
cout << 1.234 << endl;
cout << 1.2 << endl;
}
Did you even try your own example?
Trailing zeroés are NOT printed (by default).
In fact, one usually wants (!) those zeroes (they convey information and they avoid clobbering up the output).
This is achieved by cout << std::fixed.
Unless you have used std::fixed, 1.2 will produce 1.2, NOT 1.200, even with precision higher than 2.
BTW: Precision means all digits, not just those after the dot, hence precision=3 leads to 1.23 - UNLESS you go std::fixed, then only those after the dot are counted.
You might write a manipulator to achieve your formatting:
#include <cmath>
#include <iostream>
template <typename T>
struct DecimalPrecision
{
const T& value;
const unsigned decimals;
DecimalPrecision(const T& value, unsigned decimals)
: value(value), decimals(decimals)
{}
void write(std::ostream& stream) const {
std::ios_base::fmtflags flags = stream.flags();
stream.unsetf(std::ios_base::floatfield);
std::streamsize restore
= stream.precision(std::ceil(std::log10(std::abs(value))) + decimals);
stream << value;
stream.precision(restore);
stream.flags(flags);
}
};
template <typename T>
inline DecimalPrecision<T> decimal_precision(const T& value, unsigned decimals) {
return DecimalPrecision<T>(value, decimals);
}
template <typename T>
inline std::ostream& operator << (std::ostream& stream, const DecimalPrecision<T>& value) {
value.write(stream);
return stream;
}
#include <iomanip>
int main()
{
std::cout << std::setprecision(2);
double values[] = { 12345.6789, 1.23456789, 1.2 };
for(unsigned i = 0; i < sizeof(values)/sizeof(values[0]); ++i)
std::cout
<< i << ": " << values[i] << '\n'
<< " " << decimal_precision(values[i], 2) << '\n';
}

how to print Ascii code of a string in c++

I have a string and I want to print hex value of each parts ascii code.
for example if the string is "0200" the output will be 30323030 .
and here's my code:
string bit_pattern;
bit_pattern = "5678008180000000";
cout << hex << bit_pattern;
but it prints 5678008180000000 instead of 35363738303038313830303030303030
how do i fix it???
You can use the following
for (int i=0; i<bit_pattern.length(); i++)
cout << hex << (int)bit_pattern[i];
to print the ascii value (in hex format) char by char.
You're just sending the same std::string right to std::cout. Just sending the hex manipulator isn't going to magically convert all those chars.
I admit this is complete overkill, but I was bored:
#include <iostream>
#include <string>
#include <iomanip>
#include <sstream>
class ascicodes
{
std::ostringstream ss;
public:
friend std::ostream& operator <<(std::ostream& os, const ascicodes& obj)
{
os << obj.ss.str();
return os;
}
ascicodes(const std::string& s)
{
ss << std::hex << std::setfill('0');
std::for_each(s.begin(), s.end(),
[this](char ch)
{
ss << std::setw(2) << static_cast<unsigned int>(ch);
});
}
};
int main()
{
std::string bit_pattern = "5678008180000000";
std::cout << ascicodes(bit_pattern) << std::endl;
std::cout << ascicodes("A completely different string") << std::endl;
return 0;
}
Output
35363738303038313830303030303030
4120636f6d706c6574656c7920646966666572656e7420737472696e67

how to format out in c++?

I know how to use printf() to format output of float, for example:
float i = 1;
printf("%.2f", i);
but how to format the output using cout to output 2 digits after "."?
Following will do:
std::cout<<std::fixed<<std::setprecision(2)<<i;
You will also need to include iomanip
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << setprecision(2) << setiosflags(ios::fixed) << 3.141592 << endl;
}
use setprecision().
A red herring is to use std::setprecision on its own:
float f = 3.1415;
std::cout << std::setprecision(2) << f;
However, "precision" is not the same as "number of decimal places", as shown in this example.
Fortunately, and somewhat confusingly, switching the stream to "fixed-point" display changes the meaning of std::setprecision to something more akin to "setDecimalPlaces".
So, you can write this:
float f = 3.1415;
std::cout << std::fixed << std::setprecision(2) << f;
Boost format helps:
std::cout << boost::format("%.2f") % i;
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double x = 800000.0/81.0;
cout << setiosflags(ios::fixed) << setprecision(2) << x;
return 0;
}
hope this helps.........
#include <iostream>
#include <iomanip>
using namespace std;
int main () {
double f =3.14159;
cout << setprecision (5) << f << endl;
cout << setprecision (9) << f << endl;
cout << fixed;
cout << setprecision (5) << f << endl;
cout << setprecision (9) << f << endl;
return 0;
}
output..
> 3.1416
> 3.14159
> 3.14159
> 3.141590000
cout << ffmt(0, 2) << i;
Where ffmt is defined as:
class ffmt
{
int width;
int precision;
public:
ffmt( int width, int precision )
: width( width )
, precision( precision )
{
}
friend std::ostream& operator<<(
std::ostream& dest,
ffmt const& manip )
{
dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
dest.width( width );
dest.precision( precision );
}
};
You can also extend this to restore format state at the end of the full
expression; it's not too important for floating point, because most of
the time, you'll use the manipulator in front of each output, but a
manipulator which leaves the stream outputting hex is likely to lead to
surprising output later.
As a general rule, except for quicky demo or test programs, you almost
never use the standard manipulators, other that std::setw. For that
matter, in a lot of applications, you'll even avoid things like ffmt,
in favor of specific manipulators for each semantic value you have.