Setting precision of floating point number - c++

Hello guys I am new in C++
I am trying to write the function to calculate the second moment of inertia and set the precision with 3 decimal places.
In the output does not apply the 3 decimal places in the first call but the following 4 calls does applied. Here is my codes , please help me find the error and if possible please explain some details thank you very much !
double beamMoment(double b, double h) //the function that calculating the second moment of inertia
{
double I; //variables b=base, h=height, I= second moment of inertia
I = b * (pow(h, 3.0) / 12); // formular of the second momeent of inertia
ofs << "b=" << b << "," << "h=" << h << "," << "I=" << I << setprecision(3) << fixed << endl;
ofs << endl;
return I;
}
int main()
{
beamMoment(10,100);
beamMoment(33, 66);
beamMoment(44, 88);
beamMoment(26, 51);
beamMoment(7, 19);
system("pause");
return 0;
}
The output in my text file is as follow :
b=10,h=100,I=833333
b=33.000,h=66.000,I=790614.000
b=44.000,h=88.000,I=2498730.667
b=26.000,h=51.000,I=287410.500
b=7.000,h=19.000,I=4001.083

You have to set stream precision before printing a number.
ofs << 5.5555 << setprecision(3) << endl; // prints "5.5555"
ofs << setprecision(3) << 5.5555 << endl; // prints "5.555"
Stream operators << and >> are, in fact, methods that can be chained. Let's say we have a piece of example java code like:
dog.walk().stopByTheTree().pee();
In C++, if we'd use stream operators, it'd look like:
dog << walk << stopByTheTree << pee;
Operations on dog objects are executed from left to right, and the direction of "arrows" doesn't matter. These method names are just syntactic sugar.
Look here for more details.

Related

How to convert double to string with precision for total number of digits(both left and right side of the decimal)?

I am looking for a way to convert double to string in c++ such that total number of digits remain to be 10 irrespective of how many are present before and after the decimal point and irrespective of the zeroes. Examples for better understanding:
0.00000000000000000000 =expected outcome> 0.0000000000
12345.00000000000000000 =expected outcome> 12345.00000
-15.123456789012 =expected outcome> -15.12345678
I couldnt find any relevant answer. For the methods like snprintf, std::setprecision with ostringstream, to_string, Boost's lexical_cast, some of the above case fails.
Example of code:
double num = 12345.0000000000001;
std::ostringstream streamObj2;
streamObj2 << std::fixed << std::setprecision(10) << num;
std::string strObj2 = streamObj2.str();
std::cout << strObj2 << '\n';
The output = 12345.0000000000, which is not what I am expecting. Removing std::fixed gives output as 12345
What I require = 12345.00000
Please help me, thanks.
Thanks for the comments, because of which I found the answer. Using std::showpoint instead of std::fixed helped fulfill the requirement.
double num = 12345.0000000000001;
std::ostringstream streamObj2;
streamObj2 << std::showpoint << std::setprecision(10) << num;
std::string strObj2 = streamObj2.str();
std::cout << strObj2 << '\n';
Output: 12345.00000

Non-persistent formatting of streams

What's the best way (if any) to format std::*stream output in localized manner, so that formatting changes in one location won't affect the use of that stream in other locations?
That is, I'd like to set format of the stream for a single statement, not for the remaining lifetime of the stream.
The following is just a rationale for asking the above question.
Suppose you print intensity in default floating point format:
ostringstream oss;
oss << "Intensity = " << intensity << "; ";
Then print coordinates with fixed 2 digits precision:
oss << "Point = (" << fixed << setprecision(2) << pt.x << ", " << pt.y << "); ";
then, 20 lines later, print ray direction in the same fixed 2 digits format:
oss << "Direction = (" << dir.x << ", " << dir.y << "); ";
A few months later add printing of luminosity in default floating point format somewhere between printing pt and printing dir:
oss << "Luminosity = " << lum << "; ";
Oops, lum will be printed in fixed 2 digits precision because you changed oss format 20 lines before, when printing pt. Now you have to recall what you've changed in oss and rewind it for printing lum.
Moreover, after fixing format for lum you'd get another problem: dir won't be printed in fixed 2 digits anymore...
Therefore I'd like to be able to format streams locally to avoid unnecessary dependencies.
You can simply save and restore stream format flags (see std::iosbase::flags()):
fmtflags oldflags = oss.flags();
// change current format flags
oss.flags(oldflags); // <<< restore to former state
If you don't like it straight forward as mentioned above, you could also use a proxy:
class local_ostream {
public:
friend template<typename T>
local_ostream& operator<<(local_ostream& los, const& T value) {
los.os_ << value;
return los;
}
local_ostream(std::ostream& os) : os_(os), oldflags_(os.flags()) {
}
~local_ostream() {
os_.flags(oldflags_);
}
private:
std::ostream& os_;
std::iosbase::fmtflags oldflags_;
};
And use as follows:
{ local_ostream los(oss);
los << "Point = (" << fixed << setprecision(2) << pt.x << ", " << pt.y << "); ";
} // previous formatting state is restored here

C++ precision - behaviour of setprecision

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

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;

C++ const casting

I am trying to print the value of a const but it is not working. I am making a return to C++ after years so I know casting is a possible solution but I can't get that working either.
The code is as follows:
//the number of blanks surrounding the greeting
const int pad = 0;
//the number of rows and columns to write
const int rows = pad * 2 + 3;
const string::size_type cols = greeting.size() + pad * 2 + 2;
cout << endl << "Rows : " + rows;
I am trying to print the value of 'rows' without success.
You want:
cout << endl << "Rows : " << rows;
Note this has nothing to do with const - C++ does not allow you to concatenate strings and numbers with the + operator. What you were actually doing was that mysterious thing called pointer arithmetic.
You're almost there:
cout << endl << "Rows : " << rows;
The error is because "Rows : " is a string literal, thus is a constant, and generally speaking is not modified as you may think.
Going slightly further, you likely used + (colloquially used as a concatenation operation) assuming you needed to build a string to give to the output stream. Instead operator << returns the output stream when it is done, allowing chaining.
// It is almost as if you did:
(((cout << endl) << "Rows : ") << rows)
I think you want:
std::cout << std::endl << "Rows : " << rows << std::endl;
I make this mistake all the time as I also work with java a lot.
As others have pointed out, you need
std::cout << std::endl << "Rows : " << rows << std::endl;
The reason (or one of the reasons) is that "Rows : " is a char* and the + operator for char*s doesn't concatenate strings, like the one for std::string and strings in languages like Java and Python.