lexical_cast strtof strtold lose accuracy? [duplicate] - c++

This question already has answers here:
How do I print a double value with full precision using cout?
(17 answers)
Closed 6 years ago.
Here:
#include <iostream>
#include <cstdlib>
#include <boost/lexical_cast.hpp>
int main(void) {
const char * str = "277499.84";
std::cout << boost::lexical_cast<double>(str) << std::endl;
std::cout << strtof(str, NULL) << std::endl;
std::cout << strtold(str, NULL) << std::endl;
std::cout << atof(str) << std::endl;
return 0;
}
output:
277500
277500
277500
277500
Why the output are not 277499.84?

It's not the operations themselves losing accuracy, but the output.
You can use the I/O manipulator std::setprecision to control the numeric precision. The following will use the full precision of a double (assuming the stream is set for decimal output).
double value = boost::lexical_cast<double>(str);
std::cout << std::setprecision( std::numeric_limits<double>::digits10 + 1 ) << value;
Or you can use std::ios_base::precision. This is useful if you want to restore the precision to the original value after.
auto old_precision = cout.precision( std::numeric_limits<double>::digits10 + 1 );
cout << value;
cout.precision( old_precision );

Related

How do you use setprecision() when declaring a double variable in C++?

So I'm trying to learn more about C++ and I'm practicing by making a calculator class for the quadratic equation. This is the code for it down below.
#include "QuadraticEq.h"
string QuadraticEq::CalculateQuadEq(double a, double b, double c)
{
double sqrtVar = sqrt(pow(b, 2) - (4 * a * c));
double eqPlus = (-b + sqrtVar)/(2 * a);
double eqMinus = (-b - sqrtVar) / (2 * a);
return "Your answers are " + to_string(eqPlus) + " and " + to_string(eqMinus);
}
I'm trying to make it so that the double variables eqPlus and eqMinus have only two decimal points. I've seen people say to use setprecision() but I've only seen people use that function in cout statements and there are none in the class because I'm not printing a string out I'm returning one. So what would I do here? I remember way before learning about some setiosflags() method, is there anything I can do with that?
You can use stringstream instead of the usual std::cout with setprecision().
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
std::string adjustDP(double value, int decimalPlaces) {
// change the number of decimal places in a number
std::stringstream result;
result << std::setprecision(decimalPlaces) << std::fixed << value;
return result.str();
}
int main() {
std::cout << adjustDP(2.25, 1) << std::endl; //2.2
std::cout << adjustDP(0.75, 1) << std::endl; //0.8
std::cout << adjustDP(2.25213, 2) << std::endl; //2.25
std::cout << adjustDP(2.25, 0) << std::endl; //2
}
However, as seen from the output, this approach introduces some rounding off errors when value cannot be represented exactly as a floating point binary number.

How can I convert military time to regular time. the regular time must be a string [duplicate]

This question already has answers here:
how to zero pre-fill for std::to_string function?
(2 answers)
Closed 6 months ago.
I hope someone can help me. I keep getting one 0 on the minutes side. for example, for input 0000 I get 12:0 AM or for input 608 I get 6:8 AM. How can I get double 0 on the minutes side?
on main.cc I have:
#include "time_converter.h"
#include <iostream>
int main() {
int military_time;
std::cout << "Please enter the time in military time: ";
std::cin >> military_time;
// TODO: Call your function to convert from military time to regular time
// and assign its result to regular_time.
std::string regular_time;
regular_time = MilitaryToRegularTime(military_time);
std::cout << "The equivalent regular time is: " << regular_time << "\n";
return 0;
}
time_converter.h:
#include <iostream>
// Converts the time in military format to regular format.
std::string MilitaryToRegularTime(int military_time);
time_converter.cc:
#include <iostream>
std::string amorpm;
std::string MilitaryToRegularTime(int military_time) {
// TODO: convert military_time to regular time in string format.
// Hint: std::to_string() converts a given integer to a string.
int regular_hr = military_time / 100;
if (regular_hr >= 13){
regular_hr = (military_time / 100) - 12;
}
if (regular_hr == 0){
regular_hr = 12;
}
int regular_min = military_time % 100;
if (military_time >= 1200 && military_time <= 2359){
amorpm = " PM\n";
}
if (military_time >= 0000 && military_time <= 1159 ){
amorpm = " AM\n";
}
std::string regular_hr_str = std::to_string(regular_hr);
std::string regular_min_str = std::to_string(regular_min);
return regular_hr_str + ":" + regular_min_str + amorpm;
}
The function std::to_string does not have sufficient formatting options to do what you require.
However, if you instead use an object of type std::ostringstream as the target, you can use the std::setw and std::setfill I/O manipulators to accomplish what you want. You can use std::setw to set the minimum width to 2 and std::setfill to set the fill character to '0'.
After you are finished, you can convert the std::ostringstream object to a std::string using std::ostringstream::str.
#include <iostream>
#include <sstream>
#include <iomanip>
int main()
{
int hours = 6;
int minutes = 8;
std::ostringstream oss;
std::string str;
//write desired time to ostringstream object
oss <<
"The time is " <<
std::setw( 2 ) << std::setfill( '0' ) <<
hours <<
":" <<
std::setw( 2 ) << std::setfill( '0' ) <<
minutes <<
".\n";
//convert ostringstream to a string
str = oss.str();
//print the string
std::cout << "String content: " << str << '\n';
}
This program has the following output:
String content: The time is 06:08.

Stop the rounding on float c++

I am getting an issue when trying to output my float using std::cout <<
I have the following values:
vector2f = {-32.00234098f, 96.129380f} //takes 2 floats (x, y)
output: -32.0023:96.1294
What I am looking for is:
output: -32.00234098:96.129380
The actual numbers could be vary from the 7 decimal places (.0000007) to 3 decimal places (.003) so setting a fixed rounding number does not work in this case.
Any help would be great as I have tried changed to doubles as well but to no avail.
Thanks in advance!
There are 2 problems.
you need to include <iomanip> and use the std::setprecision manipulator.
To get the level of accuracy you want you will need to use doubles rather than floats.
e.g.:
#include <iostream>
#include <iomanip>
int main()
{
auto x = -32.00234098f, y = 96.129380f;
std::cout << std::setprecision(8) << std::fixed << x << ":" << y << std::endl;
// doubles
auto a = -32.00234098, b = 96.129380;
std::cout << std::setprecision(8) << std::fixed << a << ":" << b << std::endl;
}
example output:
-32.00234222:96.12937927
-32.00234098:96.12938000
You can set the output precision of the stream using std::precision manipulator.
To print trailing zeroes up to the given precision like in your example output, you need to use std::fixed manipulator.

Double numbers output gets truncated

I have a problem where I need to print some double value using basic C++ output system (such as iostream or sstream) and this value somehow gets truncated a lot.
For example:
double a = 283752.24234;
std::cout << 283752.24234 << std::endl;
std::cout << a << std::endl;
Both of the outputs will be 283752
Why is this happening and what can I do to get complete output of any double value?
Why is this happening ...
That's because the default precision is 6 and thus only the foremost 6 digits are rendered 283752.
... and what can I do to get complete output of any double value?
First option is to use a bigger precision value using the std::setprecision() I/O manipulator:
#include <iostream>
#include <iomanip>
int main(){
double a = 283752.24234;
std::cout << std::setprecision(12) << 283752.24234 << std::endl;
std::cout << std::setprecision(12) << a << std::endl;
}
See Live Demo
Second option is to use the std::fixed I/O manipulator to show the values after the decimal point:
#include <iostream>
#include <iomanip>
int main(){
double a = 283752.24234;
std::cout << std::fixed << 283752.24234 << std::endl;
std::cout << std::fixed << a << std::endl;
}
See Live Demo
Output:
283752.242340
283752.242340

double to string conversion with fixed width

I would like to print a double value, into a string of no more than 8 characters. The printed number should have as many digits as possible, e.g.
5.259675
48920568
8.514e-6
-9.4e-12
I tried C++ iostreams, and printf-style, and neither respects the provided size in the way I would like it to:
cout << setw(8) << 1.0 / 17777.0 << endl;
printf( "%8g\n", 1.0 / 17777.0 );
gives:
5.62525e-005
5.62525e-005
I know I can specify a precision, but I would have to provide a very small precision here, in order to cover the worst case. Any ideas how to enforce an exact field width without sacrificing too much precision? I need this for printing matrices. Do I really have to come up with my own conversion function?
A similar question has been asked 5 years ago: Convert double to String with fixed width , without a satisfying answer. I sure hope there has been some progress in the meantime.
This seems not too difficult, actually, although you can't do it in a single function call. The number of character places used by the exponent is really quite easy to predict:
const char* format;
if (value > 0) {
if (value < 10e-100) format = "%.1e";
else if (value < 10e-10) format = "%.2e";
else if (value < 1e-5) format = "%.3e";
}
and so on.
Only, the C standard, where the behavior of printf is defined, insists on at least two digits for the exponent, so it wastes some there. See c++ how to get "one digit exponent" with printf
Incorporating those fixes is going to make the code fairly complex, although still not as bad as doing the conversion yourself.
If you want to convert to fixed decimal numbers (e.g. drop the +/-"E" part), then it makes it a lot easier to accomplish:
#include <stdio.h>
#include <cstring> // strcpy
#include <iostream> // std::cout, std::fixed
#include <iomanip> // std::setprecision
#include <new>
char *ToDecimal(double val, int maxChars)
{
std::ostringstream buffer;
buffer << std::fixed << std::setprecision(maxChars-2) << val;
std::string result = buffer.str();
size_t i = result.find_last_not_of('\0');
if (i > maxChars) i = maxChars;
if (result[i] != '.') ++i;
result.erase(i);
char *doubleStr = new char[result.length() + 1];
strcpy(doubleStr, (const char*)result.c_str());
return doubleStr;
}
int main()
{
std::cout << ToDecimal(1.26743237e+015, 8) << std::endl;
std::cout << ToDecimal(-1.0, 8) << std::endl;
std::cout << ToDecimal(3.40282347e+38, 8) << std::endl;
std::cout << ToDecimal(1.17549435e-38, 8) << std::endl;
std::cout << ToDecimal(-1E4, 8) << std::endl;
std::cout << ToDecimal(12.78e-2, 8) << std::endl;
}
Output:
12674323
-1
34028234
0.000000
-10000
0.127800