C++ precision and truncation with file stream [duplicate] - c++

I have a file.txt with hundreds of numbers.
They have many digits (max 20) after the point and I need to get them all without truncation, otherwise they introduce errors in the following computations. I made these numbers with matlab so it has a monstrous precision but now I must replicate this behaviour in my program.
I've done this way:
fstream in;
in.open(file.txt, ios::in);
long double number;
in>>number;
I also tried this
in.precision(20);
in>>number;
before each ">>" operation but it is vain

std::numeric_limits::min std::numeric_limits::digits10 can tell you what your target's actual precision is for long double.
If you find that it's insufficient to represent your data, you probably want arbitrary precision. There are a couple of arbitrary precision number libraries you can use, none of which are standard in C++.
boost::multiprecision
GNU MP
MPFR

The following works fine on my system (Win7, VS2012):
#include <fstream>
#include <iostream>
int main (void)
{
std::ifstream file ("test.txt") ;
long double d = 0 ;
file >> d ;
std::cout.precision (20) ;
std::cout << d << "\n" ;
return 0 ;
}
The text file:
2.7239385667867091
The output:
2.7239385667867091
If this doesn't work on your system, then you need to use a third-party number library.

Related

Reading floating point values from a file drops all or part of the decimal part

I need to read floating-point values from a file.
Basic sample code of how I do this:
int main()
{
float number;
ifstream inputFile;
inputFile.open("testfile.dat");
inputFile >> number;
cout << number << endl;
return 0;
}
The first line in the file is: 13212.13131. But when I cout 'number' the displayed number is: 13212.1
The problem is part of the decimal gets dropped and in other cases all of it gets dropped. Why does this happen, and how can I solve this problem?
The point of reading the number from the file is to do mathematical calculations with it.
First, floating-point precision on output (for both std::cout and printf) is 6 decimal digits by default. You need std::setprecision() to get it print more digits. But you'll then get to the limit of float type.
On most systems float is IEEE-754 single precision, therefore it can only store about 7 digits of significant. The nearest to 13212.13131 is 1.3212130859375E4. If you need more precision, you must use double, which has about 15-16 digits of precision on most systems.
Read more: Is floating point math broken?
Try using std::setprecision():
cout << setprecision(14) << number << endl;
You will need to
#include <iomanip>
If that doesn't solve it you should try debugging it and see what the number actually is (13212.13131 or 13212.1).

C++ precision of numbers and truncation with fstream

I have a file.txt with hundreds of numbers.
They have many digits (max 20) after the point and I need to get them all without truncation, otherwise they introduce errors in the following computations. I made these numbers with matlab so it has a monstrous precision but now I must replicate this behaviour in my program.
I've done this way:
fstream in;
in.open(file.txt, ios::in);
long double number;
in>>number;
I also tried this
in.precision(20);
in>>number;
before each ">>" operation but it is vain
std::numeric_limits::min std::numeric_limits::digits10 can tell you what your target's actual precision is for long double.
If you find that it's insufficient to represent your data, you probably want arbitrary precision. There are a couple of arbitrary precision number libraries you can use, none of which are standard in C++.
boost::multiprecision
GNU MP
MPFR
The following works fine on my system (Win7, VS2012):
#include <fstream>
#include <iostream>
int main (void)
{
std::ifstream file ("test.txt") ;
long double d = 0 ;
file >> d ;
std::cout.precision (20) ;
std::cout << d << "\n" ;
return 0 ;
}
The text file:
2.7239385667867091
The output:
2.7239385667867091
If this doesn't work on your system, then you need to use a third-party number library.

How to multiply integers larger than uint64?

#include <iostream>
#include <limits>
int main(void) {
cout << std::numeric_limits<uint64_t>::max();
return 0;
}
The code above outputs (on my machine) 18446744073709551615, but I'm trying to multiply numbers that have at least 25 digits. How to properly handle a multiplication of 2 integers that are larger than uint64?
You need to use a library that handles big numbers. Here are some of them:
The GNU Multiple Precision Arithmetic Library
https://gmplib.org/
C++ Big Integer Library
https://mattmccutchen.net/bigint/
Boost.Multiprecision
http://www.boost.org/doc/libs/1_55_0/libs/multiprecision/doc/html/index.html

Find Pi to the Nth Digit

I'm beginning to teach myself C++ until my class starts in the fall. I was wondering if you might be able to help me come up with a better way to ask the user for the number of digits they want for the number pi, and then display it. My problem is that using pi = atan(1)*4 isn't precise past around 10 decimal places. Is there a better built in number that has pi to at least 20 decimal places? Here is what I have so far, thanks!
#include <iostream>
#include <string>
#include <iomanip>
#include <ios>
#include <sstream>
using namespace std;
using std::setprecision;
using std::streamsize;
int main()
{
double pi = atan(1)*4;
int input = 0;
while(true)
{
cout << "Please enter how many digits of PI you would like to see (Max 20): ";
cin >> input;
if(input > 0 && input <= 20)
{
break;
}
else
{
cout << "That's not a valid number! Try again." << endl;
}
}
streamsize prec = cout.precision();
cout << setprecision(input);
cout << "Here you go: " << pi <<endl;
system("pause");
}
The easiest way to do this would probably just have a std::string containing the digits that you want ("3.14159265358979323846264338327950288419"), and then just print the first input digits beyond the decimal point.
I would say that this is less of a C++ problem, and more of a math problem. There are several infinite series that converge to the true value of Pi very quickly. Have you looked at the Wikipedia article on this topic?
As for being precise to nine or ten digits, you may run into rounding issues using double (especially with certain calculation methods). I would consider looking into an arbitrary-precision math library. I'm a big fan of MPFR, but I'm sure Boost has something analogous if that's more your thing (keep in mind that Boost is a C++ library, whereas MPFR is a C library [although you can, of course, use C code from C++]).
MPFR does have a C++ wrapper, but in general I don't enjoy using it as much as the C functions, since the last time I looked at it (admittedly, a while ago), it wasn't quite as feature-complete.
It's probably worth noting also that, since your goal is to learn C++, and not to learn how to efficiently approximate Pi, it might be preferrable to solve this problem by e.g. just retrieving the first n-digits from a hard-coded string instead, as Chris said.
A double will have 53 bits of precision. Each bit gives about 1/3 of a decimal digit (log(10)/log(2) to be precise), which means that we get approximately 53/3 digits out of a double. That should give 17 digits (including the 3 at the beginning). It's plausible that atan(1) isn't giving quite all the digits of pi/4 either (because atan as well as any other trigonometric function is an approximation).
If you want many more digits than about 12-14 digits, you will need to use a "big number" library, and there are a number of "clever" ways to calculate the decimals of PI.

Maximum Width of a Printed Double in C++

I was wondering, how long in number of characters would the longest a double printed using fprintf be? My guess is wrong.
Thanks in advance.
Twelve would be a bit of an underestimate. On my machine, the following results in a 317 character long string:
#include <limits>
#include <cstdio>
#include <cstring>
int main()
{
double d = -std::numeric_limits<double>::max();
char str[2048] = "";
std::sprintf(str, "%f", d);
std::size_t length = std::strlen(str);
}
Using %e results in a 14 character long string.
Who knows. The Standard doesn't say how many digits of precision a double provides other than saying it (3.9.1.8) "provides at least as much precision as float," so you don't really know how many characters you'll need to sprintf an arbitrary value. Even if you did know how many digits your implementation provided, there's still the question of exponential formatting, etc.
But there's a MUCH bigger question here. Why the heck would you care? I'm guessing it's because you're trying to write something like this:
double d = ...;
int MAGIC_NUMBER = ...;
char buffer[MAGIC_NUMBER];
sprintf(buffer, "%f", d);
This is a bad way to do this, precisely because you don't know how big MAGIC_NUMBER should be. You can pick something that should be big enough, like 14 or 128k, but then the number you picked is arbitrary, not based on anything but a guess that it will be big enough. Numbers like MAGIC_NUMBER are, not suprisingly, called Magic Numbers. Stay away from them. They will make you cry one day.
Instead, there's a lot of ways to do this string formatting without having to care about buffer sizes, digits of precision, etc, that let you just get on with the buisness of programming. Streams is one:
#include <sstream>
double d = ...;
stringstream ss;
ss << d;
string s = ss.str();
cout << s;
...Boost.Format is another:
#include <boost\format\format.hpp>
double d = ... ;
string s = (boost::format("%1%") % d).str();
cout << s;
Its defined in limits:
std::cout << std::numeric_limits<double>::digits << "\n";
std::cout << std::numeric_limits<double>::digits10 << "\n";
Definition:
digits: number of digits (in radix base) in the mantissa
Equivalent to FLT_MANT_DIG, DBL_MANT_DIG or LDBL_MANT_DIG.
digits10: Number of digits (in decimal base) that can be represented without change.
Equivalent to FLT_DIG, DBL_DIG or LDBL_DIG for floating types.
See: http://www.cplusplus.com/reference/std/limits/numeric_limits/
Of course when you print stuff to a stream you can use the stream manipulators to limit the size of the output.
you can decide it by yourself..
double a=1.1111111111111111111111111111111111111111111111111;
printf("%1.15lf\n", a);
return 0;
./a.out
1.111111111111111
you can print more than 12 characters..
If your machine uses IEEE754 doubles (which is fairly widespread now), then the binary precision is 53 bits; The decimal equivalent is approximately 15.95 (calculated via logarithmic conversion), so you can usually rely on 15 decimal digits of precision.
Consult Double precision floating-point format for a brief discussion.
For a much more in-depth study, the canonical paper is What Every Computer Scientist Should Know About Floating-Point Arithmetic. It gets cited here whenever binary floating point discussions pop up, and is worth a weekend of careful reading.