2

The following is my console input/output.

Please enter a real number: -23486.33 Characters checked: 9

Thank you. The real number you entered is -23486.3

The value I entered is -23486.33, but yet cout prints it as -23486.3. The relevant code is below:

#include <iostream>
#include <string>
#include <cctype>

using namespace std;

//  Function prototype (declaration)
string readDouble();
bool isValidDouble(string);

int main()
{
    string value;
    double number;

    value = readDouble();
    while (!isValidDouble(value)) {
        cout << "The number you entered is not a valid integer." << endl;
        value = readDouble();
    }

    number = atof(value.c_str());
    cout << "Thank you." << endl
         << "The real number you entered is " << number << endl;
}

When debugging, I check the value of number right after the method call atof(value.c_str())l;. Number is shown to have a value of -23486.33. So what happens between that and the print out by cout? In no part of my code do I set the precision of cout or make it fixed.

If you have any questions, please let me know.

manlio
  • 18,345
  • 14
  • 76
  • 126
Mickster37
  • 155
  • 2
  • 10
  • Some rounding is desirable to avoid excessively long output. For example, the nearest IEEE 754 64 bit binary to decimal -23486.33 is -23486.330000000001746229827404022216796875. That is probably the value of your `number`. – Patricia Shanahan Nov 19 '13 at 18:32
  • @PatriciaShanahan In this case, however, why trim my number (which the debugger shows as having a value of -23486.33) to -23486.3 ? Even if the number was one with an excessively large amount of decimal places, as in your example, why keep trimming past the set of 0s ? – Mickster37 Nov 21 '13 at 07:17
  • 1
    The ostream formatting is based on a width and precision, rather than on the value of the number. In contrast, Java's Double toString converts a double to the shortest string that would convert back to the same double. It would show your number as -23486.33. – Patricia Shanahan Nov 21 '13 at 08:51
  • @PatriciaShanahan Makes sense now. – Mickster37 Nov 22 '13 at 20:17

4 Answers4

2

Have you tried

std::cout << std::setprecision(2) << number;

look at: http://www.cplusplus.com/reference/iomanip/setprecision/

frank
  • 147
  • 6
  • I have seen this. This would solve this specific problem but I need the above program to support doubles with more than 2 decimal places. – Mickster37 Nov 19 '13 at 06:23
  • @Mickster37: floating point values are stored in binary, not decimal, so some decimal values are only represented as approximations in binary. You won't be able to read and write exact decimal numbers using `float` or `double`. – dreamlax Nov 19 '13 at 06:40
  • @Mickster: in particular, there is no difference between `-23486.3` and `-23486.30` – MSalters Nov 19 '13 at 07:46
  • @dreamlax I understand that much. I wouldn't have expected an exact decimal number if my number had a lot of decimal positions, but is this still the case for numbers with few decimal positions too? – Mickster37 Nov 21 '13 at 07:12
  • @MSalters no, but there is a difference between -23486.33 and -23486.3 – Mickster37 Nov 21 '13 at 07:13
  • This only seems to work for me if I insert 'fixed' into the stream between set precision and number, e.g.: std::cout << setprecision(2) << fixed << number. No idea why. – Matt Parkins Jan 08 '14 at 13:42
2

-23486.3 is displayed because std::cout prints only 6 digits by default.

To print back a number entered from standard input (convertion text → floating number → text), you can use set_precision with digits10 as precision:

double d = -23486.33;
int precision = std::numeric_limits<double>::digits10;
std::cout << std::setprecision(precision) << d << std::endl;

This displays:

-23486.33


To print a number with full precision (usually for convertion floating number → text → floating number), you can use set_precision with max_digits10 as precision:

double d = -23486.33;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;

This displays:

-23486.330000000002

Here the printed number is not the same because -23486.33 doesn't have an exact representation in IEEE encoding (expressed in base 2 instead of base 10).


For more details with digits10 and max_digits10, you can read:

Daniel Laügt
  • 1,097
  • 1
  • 12
  • 17
1

You can set the precision to the maximum limit for double.

The code snippet is here:

#include <iostream>
#include <limits>
#include <iomanip>

using namespace std;
double number = ... // your double value.
cout << setprecision(numeric_limits<double>::digits10) << number << endl; 
chancyWu
  • 14,073
  • 11
  • 62
  • 81
  • What exactly does this do? More comments would be helpful. – Mickster37 Nov 21 '13 at 07:13
  • @Mickster37 it set the precision to the maximum limits for double, and fixed is format specifier which can trim the no need 0s – chancyWu Nov 21 '13 at 07:32
  • Very helpful code snippet! I'm giving the correct answer to someone else though who responded more directly to the question. Thank you. – Mickster37 Nov 22 '13 at 20:16
  • @DanielLaügt Hi Daniel, `setprecision` set the precision for the digits both before and after the decimal point. It's easy to test by the number `-23456.111111119112345` and `-123456.111111119112345`, they will be `-23456.1111111191` and `-123456.111111119` respectively. – chancyWu Jan 19 '16 at 03:16
  • @DanielLaügt Yes, fixed should be removed. – chancyWu Jan 20 '16 at 01:56
1

Set a precision when you output a double and keep precision explicitly when you compare them.

When you convert a string presentation of a DEC number to a double(float point number presentation), the data in the memory might not be mathematically equal to the string presentation. It's the best approximation by a float point number presentation, and vise versa.

Zhongzhi
  • 436
  • 3
  • 6
  • Understandable. However, as noted in my original post, when using the debugger to check the value of "number", I am shown -23486.33 but it prints out -23486.3 . It seems to me that the loss of precision occurs when printing out the float, not when converting from string to float. – Mickster37 Nov 21 '13 at 07:15
  • 1
    @Mickster37 The data in memory might not be just -23486.33. It could be something like -23486.3300000000002. The program didn't know the precision(for output) you wanted. So it decided for you. – Zhongzhi Nov 21 '13 at 08:31
  • That makes perfect sense. Great explanation. – Mickster37 Nov 22 '13 at 20:18