C++ precision - behaviour of setprecision - c++

As I understand it the setprecision function specifies the minimal precision but when I run the following code I get only 3 numbers after the decimal point:
int main()
{
double a = 123.4567890;
double b = 123.4000000;
std::cout << std::setprecision(5) << a << std::endl; // Udesireble
std::cout.setf(std::ios::fixed);
std::cout << std::setprecision(5) << a << std::endl; // Desireble
std::cout << std::setprecision(5) << b << std::endl; // Udesireble
std::cout.unsetf(std::ios::fixed);
std::cout << std::setprecision(5) << b << std::endl; // Desireble
return 0;
}
which prints:
123.46 // Udesireble
123.45679 // Desireble
123.40000 // Udesireble
123.4 // Desireble
Is there any way I can avoid checking the number of digits after the decimal point myself in order to know whether to set fixed ?

My impression is that you will need to format to string first, and then replace trailing zeros with spaces.

For the streams, you can use two functions.
setfill(char_type c), which set the character to write, to match with the number of needed character (more information here)
There is the setw(int) function, which set the width of field of the value to display. (documentation here )
Using these functions, you may have a solution

Related

How to return a "double" value to two decimal places in C++

double calc_percent_of_daily_sugar(int sugar) {
double result;
result = sugar/avg_sugar_intake;
return result*100;
}
I'm trying to get this function to return the result to only 2 decimal places however when I try to use cout << setprecision(2) << result; then there are still more than 2 places in the number
Apologies if this is a nooby or stupid question.
*How to print a “double” value to two decimal places in base 10 in C++
Use std::fixed to print it in decimal.
std::cout << std::setprecision(2) << std::fixed << 123.4567 << std::endl;
// 123.46
See: https://en.cppreference.com/w/cpp/io/manip/fixed

Conversion of string to double without scientific notation in C++

I have a string variable and want to convert it into double without any scientific notation. I tried using std::stod but that doesn't work.
std::stringstream timestamp;
timestamp << t_val;
string test = timestamp.str();
cout << test << endl; // this gives 1506836639.96
double d = std::stod(test);
cout << d << endl; // This gives 1.50684e+09 instead of 1506836639.96
I tried using setprecision and fixed but I couldn't store the result into a variable. Is there a way I can store the value of test (1506836639.96) as a double?
The scientific notation has to do with std::cout, not the way the value is stored, so you must use std::fixed before you print the value:
std::cout << std::fixed << std::setprecision(2) << d << std::endl;
As you can see in the demo, this works fine, it should work for you as well.
As #goodvibration commented std::to_string also works but it's not possible to redefine, in a simple manner, the default number or decimal places in this case.
std::cout << std::to_string(d) << std::endl;
Live demo

std::cout with floating number

I'm using visual studio 2015 to print two floating numbers:
double d1 = 1.5;
double d2 = 123456.789;
std::cout << "value1: " << d1 << std::endl;
std::cout << "value2: " << d2 << std::endl;
std::cout << "maximum number of significant decimal digits (value1): " << -std::log10(std::nextafter(d1, std::numeric_limits<double>::max()) - d1) << std::endl;
std::cout << "maximum number of significant decimal digits (value2): " << -std::log10(std::nextafter(d2, std::numeric_limits<double>::max()) - d2) << std::endl;
This prints the following:
value1: 1.5
value2: 123457
maximum number of significant decimal digits (value1): 15.6536
maximum number of significant decimal digits (value2): 10.8371
Why 123457 is printed out for the value 123456.789? Does ANSI C++ specification allow to display anything for floating numbers when std::cout is used without std::setprecision()?
The rounding off happens because of the C++ standard which can be seen by writing
std::cout<<std::cout.precision();
The output screen will show 6 which tells that the default number of significant digits which will be printed by the std::cout statement is 6. That is why it automatically rounds off the floating number to 6 digits.
What you have have pointed out is actually one of those many things that the standardization committee should consider regarding the standard iostream in C++. Such things work well when you write :-
printf ("%f\n", d2);
But not with std::cout where you need to use std::setprecision because it's formatting is similar to the use of %g instead of %f in printf. So you need to write :-
std::cout << std::setprecision(10) << "value2: " << d2 << std::endl;
But if you dont like this method & are using C++11 (& onwards) then you can also write :-
std::cout << "value2: " << std::to_string(d2) << std::endl;
This will give you the same result as printf ("%f\n", d2);.
A much better method is to cancel the rounding that occurs in std::cout by using std::fixed :-
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::fixed;
double d = 123456.789;
std::cout << d;
return 0;
}
Output :-
123456.789000
So I guess your problem is solved !!
I think the problem here is that the C++ standard is not written to be easy to read, it is written to be precise and not repeat itself. So if you look up the operator<<(double), it doesn't say anything other than "it uses num_put - because that is how the cout << some_float_value is implemented.
The default behaviour is what print("%g", value); does [table 88 in n3337 version of the C++ standard explains what the equivalence of printf and c++ formatting]. So if you want to do %.16g you need to change the precision by calling setprecision(16).

Double: using the actual number of decimal places

I'm creating a calculator program, but I don't know how to set the precision of the decimal places of the calculated answer so that the actual number of decimal places is displayed.
Examples:
-If the answer is 6, it would display 6, not 6.0000000
-if the answer is 8.23, it would display 8.23, not 8.23000000
etc.
How would I set the precision as such?
In C++, use the method precision to set the number of needed placeholders, like:
double f = 3.14159;
std::cout.unsetf ( std::ios::floatfield ); // floatfield not set
std::cout.precision(5); //will output 5 digits after point
std::cout << f << '\n';
std::cout.precision(10); //will output 10 digits after point, like 3.1415900000
std::cout << f << '\n';
std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
std::cout << f << '\n';
To remove any trailing zeroes, you can use
std::cout.precision(0);
Basically, you can set:
std::cout.precision(6); // 6 digits
or whatever value you need. Or:
std::cout << std::setprecision(5) << my_double_value << std::endl;
iostream provides a setprecision function:
double f =3.14159;
std::cout << std::setprecision(5) << f << '\n';
std::cout << std::setprecision(9) << f << '\n';
std::cout << std::fixed;
std::cout << std::setprecision(5) << f << '\n';
std::cout << std::setprecision(9) << f << '\n'
Output will be:
3.1416
3.14159
3.14159
3.141590000
There isn't an "actual number of decimal places". Double precision has a number of binary places but these don't map reliably into a number of decimal places. An easy example is 1.0/10,0 which should be 0.1 but is actually a number quite close to 0.1; how many decimal places you show for sums such as these is thus not a quality of the double itself but rather of how many decimal places you want to show.
How you can truncate to the number you want has been discussed in the other answers.
This will work:
printf("%g",value);

ostream: prefix a positive number with a space

In C a space can be included in a printf formatting flag which results in positive numbers being prefixed with a space. This is a useful feature for aligning signed values. I can't figure out how to do the same in C++. In C:
double d = 1.2;
printf("%f\n",d);
printf("%+f\n",d);
printf("% f\n",d);
produces:
1.2
+1.2
1.2
Using ostream, I can do the first two, but how do I do the third?
int d = 1.2;
std::cout << d << std::endl;
std::cout << std::showpos << d << std::endl;
// ??????????????
EDIT: There seems to be some confusion about whether or not I just want to prefix all of my values with a space. I only want to prefix positive values with a space, similar to a) like the printf space flag does and b) similar to what showpos does, except a space rather than a '+'. For example:
printf("%f\n", 1.2);
printf("%f\n", -1.2);
printf("% f\n", 1.2);
printf("% f\n", -1.2);
1.2
-1.2
1.2
-1.2
Note that the third value is prefixed with a space while the fourth (negative) value is not.
You can use setfill and setw, like this:
cout << setw(4) << setfill(' ') << 1.2 << endl;
cout << setw(4) << setfill(' ') << -1.2 << endl;
This produces the following output:
1.2
-1.2
Don't forget to include <iomanip> in order for this to compile (link to ideone).
I don't have my standard with me and I'm doing this stuff too rarely to be confident about it: There are two ingredients to achieving this with IOStreams:
Use std:: showpos to have an indicator of positive values be shown. By default this will use +, of course.
I think the + is obtained using std::use_facet<std::ctype<char> >(s.get_loc()).widen('+'). To turn this into a space you could just use a std::locale with a std::ctype<char> facet installed responding with a space to the request to widen +.
That is, something like this:
struct my_ctype: std::ctype<char> {
char do_widen(char c) const {
return c == '+'? ' ': this->std::ctype<char>::do_widen(c);
}
};
int main() {
std::locale loc(std::locale(), new my_ctype);
std::cout.imbue(loc);
std::cout << std::showpos << 12.34 << '\n';
}
(the code isn't tested and probably riddled with errors).
How about
std::cout << (d >= 0 ? " ":"") << d << std::endl;
std::cout << " " << my_value;
If you need space only for positive:
if (my_value >=0 ) cout << " "; cout << my_value;