Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm brand new to programming so please answer in simple terms.
I'm trying to print a double. The program ask the user to input as many digits of pi as he can remember, and then it is supposed to print it back to him. But it always prints back 6 decimal places. I need it to print the amount of decimals that were originally put in. so 3.14 is to decimals, while 3.141592654 is 9. so it prints what was put in.
You need a combination of std::fixed followed by std::precision
Like this:
double f =3.14159;
std::cout << std::fixed;
std::cout << std::setprecision(5) << f << '\n'; // prints 5 decimals
std::cout << std::setprecision(9) << f << '\n'; // prints 9 decimals
Now what to pass to std::setprecision() as an argument needs to be calculated from the input you are getting.
Numbers are numbers, not strings. They have actual precision governed by their type (float, double etc).
You cannot "remember" the logical precision originally provided, unless you take input as string, count the precision yourself, then convert to a number.
Then you use formatting options to reproduce that precision level in the output.
Alternatively, just stick with strings.
For this specific case only (comparing how precise was the entered pi), use a std::string rather than a double. If someone who knows a couple of thousands of digits uses your program, the double-precision floating point variable will not be precise enough for a comparison. You will have to store a reference pi as a string too.
Incidentally, with this approach you will no longer have the issue of remembering how many decimal places were entered.
You might want to investigate the differences between decimal and binary representations of numbers.
Your user enters a decimal representation, i.e. each symbol represents a digit from 0 to 9.
On the other hand, a double is a binary representation.
Some numbers can be expressed with a decimal representation but have no equivalent in binary representation. For instance you cannot express 0.3 with a finite number of binary symbols.
That's why you should keep your input as decimal, for instance by using a string.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
How can I add a scientific and a float number ? I have something like
var1 0.99999899 var2 3.5008552e-05 sum 3.5008552e-05
but what I dont understand is why in the first place var2 is shown as scientific while in the first place I declared
double var1, var2;
so, actually their sum is just var2...
thanks
a
The way a floating-point value is displayed is down to the mechanism by which you display it. It is not a property of the value itself, nor is it in any way stored within the variable:
A number is a number is a number. What you call "scientific" is not a class of numbers. It's a class of representations of numbers. The same way that "twelve" and "12" and "XII" and "a dozen" and "IIIIIIIIIIII" all represent the same number. This "scientific" thing only exists when you decide to represent the number in some specific way (i.e. when you output it). Calculations don't "turn numbers into scientific" the same way that saying that "2 * 6 is twelve" doesn't turn numbers into English words. The variables always store the numbers not the representations. — R. Martinho Fernandes
Your display mechanism — std::cout? — is choosing the best way to output the value. You can override this with IO manipulators such as std::fixed, though it's pretty fiddly sometimes to get it just how you want it, due to library limitations.
If you have <stdio.h> available then you may use int printf ( const char * format, ... ); the format specifier would look something like this: printf("%.5f", your_double) where 5 is the number of digits you want after the decimal point, the default is 6.
(printf docs)
This question already exists:
gfortran represents REAL incorrectly [duplicate]
Closed 8 years ago.
This question has not been previously answered. I am trying to represent a real or any number for that matter in Fortran correctly. What gfortran is doing for me is way off. For example when I declare the variable REAL pi=3.14159 fortran prints pi = 3.14159012 rather than say 3.14159000. See below:
PROGRAM Test
IMPLICIT NONE
REAL:: pi = 3.14159
PRINT *, "PI = ",pi
END PROGRAM Test
This prints:
PI = 3.14159012
I might have expected something like PI = 3.14159000 as a REAL is supposed to be accurate to at least 8 decimal places.
I'm in a good mood, so I'll try to answer this question, which is basic knowledge which can be easily googled (as already pointed out in the comments to this and your former question).
Luckily, Fortran provides some really interesting intrinsics to get some understanding of floating point numbers.
The 8 digits, you are talking about, are a rule of thumb and can be related to the function EPSILON(x), which prints the smallest deviation from 1, which can be represented within the chosen model (e.g. REAL4). This value is actually 1.19e-7 which means, that your 8th digit is most likely wrong. I write most likely, because some numbers can be represented exactly.
In the case of PI, the smallest representable deviation can be printed using the intrinsic SPACING(PI). This shows a value of 2.38e-7, which is slightly larger than the epsilon and still allows for 7 correct digits.
Now, why does your value of PI get stored as 3.14159012? When you store a floating point number, you always store the nearest representable number.
Using the value of spacing, we can get the possible values for your pi. Possible numbers and their differences to your value of 3.14159 are:
3.14158988 1.20E-007
3.14159012 -1.18E-007
3.14159036 -3.56E-007
As you can see, 3.14159012 is the nearest possible value to 3.14159 and is thus stored and printed.
It is common for the last two digit to be erroneous. It is called floating point error.
Check this:
Week 1 - Lecture 2: Binary storage and version control / Fixed and floating point real numbers (9-08).mp4
#
https://class.coursera.org/scicomp-002/lecture
This question already has answers here:
Floating point inaccuracy examples
(7 answers)
Closed 8 years ago.
I have a string that stores a decimal value, for instance, "0.10". I want to convert this to a float. But when I use atof to do it, the number I get is not exactly the value it should be. I'm writing some complicated algorithms involving some number crunching of decimal values, so this is throwing my final results off.
Here is some simple code that describes the problem I'm having. Here, I simply put a decimal value into a string, convert it to a float with atof, and print it out with cout. The result I'm getting shows that atof is adding a tiny decimal number to the final value.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
string value = "0.10";
float valueAsFloat = atof(value.c_str());
cout.precision(20);
cout << valueAsFloat << endl;
return 0;
}
The output is:
0.10000000149011611938
Any ideas? I'm using the GNU g++ compiler on Ubuntu. Could it be a bug with this compiler that's causing the problem? If so, is there any other way to convert the value to a float and get the right value? Thanks.
Edit: While that question gives a partial explanation as to why this happens, it does not give a full value, and it only offers a single solution which may or may not work. Therefore, I thinking leaving this question open as a separate question is valid.
This is not an issue with the conversion activity, but the inherent precision (or lack of precision) of the float. Different compilers will have different precision. Also, as you perform more and more mathematical operations in serial where the output of one is the input into the next, the precision is further eroded. The lack of precision comes from using binary (discrete) data to approximate values in the continuous real number set.
You may choose to use a "double" instead, and traditionally it has double the precision of a float. However, some modern compilers use the same precision for "double" as float.
The issue can be reduced by choosing different compilers, different data types, but the ultimate problem will remain.
In C++, can I write and read back a float (or double) in text format without losing precision?
Consider the following:
float f = ...;
{
std::ofstream fout("file.txt");
// Set some flags on fout
fout << f;
}
float f_read;
{
std::ifstream fin("file.txt");
fin >> f;
}
if (f != f_read) {
std::cout << "precision lost" << std::endl;
}
I understand why precision is lost sometimes. However, if I print the value with enough digits, I should be able to read back the exact same value.
Is there a given set of flags that is guaranteed to never lose precision?
Would this behaviour be portable across platforms?
If you don't need to support platforms that lack C99 support (MSVC), your best bet is actually to use the %a format-specifier with printf, which always generates an exact (hexadecimal) representation of the number while using a bounded number of digits. If you use this method, then no rounding occurs during the conversion to a string or back, so the rounding mode has no effect on the result.
Have a look at this article: How to Print Floating-Point Numbers Accurately and also at that one: Printing Floating-Point Numbers Quickly and Accurately.
It is also mentioned on stackoverflow here, and there is some pointer to an implementation here.
if I print the value with enough digits, I should be able to read back the exact same value
Not if you write it in decimal - there's not an integer relationship between the number of binary digits and the number of decimal digits required to represent a number. If you print your number out in binary or hexadecimal, you'll be able to read it back without losing any precision.
In general, floating point numbers are not portable between platforms in the first place, so your text representation is not going to be able to bridge that gap. In practice, most machines use IEEE 754 floating point numbers, so it'll probably work reasonably well.
You can't necessarily print the exact value of a "power of two" float in decimal.
Think of using base three to store 1/3, now try and print 1/3 in decimal perfectly.
For solutions see: How do you print the EXACT value of a floating point number?
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why don't operations on double-precision values give expected results?
I am experiencing a peculiar problem in C++. I created a variable of type Double. Then I did some calculations with some values assigned to other variables and assigned the result to the double variable I declared. It gave me a result with a long decimal part. I want it to round to only 2 decimal places. and store it into the variable. But even after several attempt rounding, I couldnt round it to 2 decimal places.
Then I tried another way to check what the real problem is. I created a Double variable and assigned it the value 1.11. But when I debugged it by putting a break point and added a watch for that variable, I could find that the value now stored in the variable is 1.109999999999.
My question is, why is it showing like that? Isnt there any way in which we can round the variable into two decimal places? Why is it showing a long decimal part even if we assign a number with just two decimal places?
Please suggest a way to store numbers - whether it is calculated or directly assigned - as it is, in a double variable rather than a number with a long decimal part.
In the set of double values, there is no such thing as the number 1.11 because internally, double uses a binary representation (as opposed to humans who are used to a decimal representation). Most finite decimal numbers (such as 1.11) have an infinite representation in binary, but since memory is limited, you lose some precision because of rounding.
The closest you can get to 1.11 with the double data type is 1.1100000000000000976996261670137755572795867919921875, which is internally represented as 0x3ff1c28f5c28f5c3.
Your requirement of two decimal places sounds like you are working with money. A simple solution is to store the cents in an integer (as opposed to the dollars in a double):
int cents = 111;
This way, you don't lose any precision. Another solution is to use a dedicated decimal data type.
the floating-point types like float and double are not 100% precise. They may store 14.3 as 14.299999... and there is nothing wrong about that. That is why you should NEVER compare two floats or doubles with == operator, instread you should check if the absolute value of their difference is smaller than a certain epsilon, like 0.000000001
Now, if you want to output the number in a pleasant way, you can use setprecision from <iomanip>
E.g.
#include <iostream>
#include <iomanip>
int main()
{
double d = 1.389040598345;
std::cout << setprecision(2) << d; //outputs 1.39
}
If you want to obtain the value of d rounded 2 decimal places after the point, then you can use this formula
d = floor((d*100)+0.5)/100.0; //d is now 1.39
Not every decimal number has an exact, finite, binary floating-point representation. You've already found one example, but another one is 0.1 (decimal) = 0.0001100110011... (binary).
You either need to live with that, or use a decimal floating-point library (which will be less efficient).
My recommendation would be to store numbers to full precision, and only round when you need to display them to humans.