0

I am trying to write a calculator in C++ that does the basic functions of /, *, -, or + and shows the answer to two decimal places (with 0.01 precision).

For example 100.1 * 100.1 should print the result as 10020.01 but instead I get -4e-171. From my understanding this is from overflow, but that's why I chose long double in the first place!

#include <iostream>
#include <iomanip>
using namespace std;

long double getUserInput()
{
    cout << "Please enter a number: \n";
    long double x;
    cin >> x;
    return x;
}

char getMathematicalOperation()
{
    cout << "Please enter which operator you want "
            "(add +, subtract -, multiply *, or divide /): \n";
    char o;
    cin >> o;
    return o;
}

long double calculateResult(long double nX, char o, long double nY)
{
// note: we use the == operator to compare two values to see if they are equal
// we need to use if statements here because there's no direct way 
// to convert chOperation into the appropriate operator

if (o == '+') // if user chose addition
    return nX + nY; // execute this line
if (o == '-') // if user chose subtraction
    return nX - nY; // execute this line
if (o == '*') // if user chose multiplication
    return nX * nY; // execute this line
if (o == '/') // if user chose division
    return nX / nY; // execute this line
return -1; // default "error" value in case user passed in an invalid chOperation
}

void printResult(long double x)
{
    cout << "The answer is: " << setprecision(0.01) << x << "\n";
}

long double calc()
{
// Get first number from user
    long double nInput1 = getUserInput();

// Get mathematical operations from user
    char o = getMathematicalOperation();

// Get second number from user
    long double nInput2 = getUserInput();

// Calculate result and store in temporary variable (for readability/debug-ability)
    long double nResult = calculateResult(nInput1, o, nInput2);

// Print result
    printResult(nResult);
    return 0;
}
Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Try `setprecision(2)`. – IllusiveBrian Apr 25 '15 at 05:20
  • 1
    BTW, your question has a strange & confusing title (as if you want to compute numbers with 100 digits of precision). You really want 2 decimal places, not 100! I was understanding you are asking about [bignums](http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic), so was about to suggest [GMPlib](https://gmplib.org/) – Basile Starynkevitch Apr 25 '15 at 06:07
  • how would you have stated the title based on the actual brief paragraph description? – theresthatguy Apr 25 '15 at 06:10

4 Answers4

4

setprecision tells it how many decimal places you want as an int so you're actually setting it to setprecision(0) since 0.01 get truncated. In your case you want it set to 2. You should also use std::fixed or you'll get scientific numbers.

void printResult(long double x)
{
    cout << "The answer is: " << std::fixed << setprecision(2) << x << "\n";
}

working example

AliciaBytes
  • 7,300
  • 6
  • 36
  • 47
  • When I added your suggestion "fixed << setprecision(2)", my output is now -0.00. If I do setprecision(2) but drop the fixed I get -4.2e-171. – theresthatguy Apr 25 '15 at 06:20
  • -4.2e-171 is a very very low number and almost 0. You sure your input is correct? – AliciaBytes Apr 25 '15 at 06:28
  • I checked the sizeof(long long) and it is 12 bytes, perhaps this is why I am not getting the desired displayed result? – theresthatguy Apr 25 '15 at 06:28
  • @theresthatguy - did this answer solve your problem? I assume it did since it has been accepted. Or? – Support Ukraine Apr 25 '15 at 06:41
  • No, I'm still getting -4.2e-171. I've been trying to solve this problem all evening. (100.1 * 100.1) felt like a good equation to test a long double – theresthatguy Apr 25 '15 at 06:44
  • I can't see anything wrong with the code and it works properly here. Are you maybe using MingW compiler on windows? It seems like they have had problems with printing `long doubles`: http://oldwiki.mingw.org/index.php/long%20double – AliciaBytes Apr 25 '15 at 06:51
  • @Raphael - I don't see anything wrong with the code. However, the problem faced by me and theresthatguy wasn't solved though. My problem is probably mingw as described by your link (+1 for that). Are you using windows also - if so which compiler. I'll copy your link into my answer if you don't mind. Thanks. – Support Ukraine Apr 25 '15 at 07:15
  • @nielsen can't recommend a compiler since I'm on Linux myself. That link was simply the only explanation I found for such a problem. – AliciaBytes Apr 25 '15 at 07:29
2

It is not due to overflow you get the strange result. Doubles can easily hold numbers in the range you are showing.

Try to print the result without setprecision.

EDIT: After trying

long double x = 100.1;
cout << x << endl;

I see that it doesn't work on my Windows system.

So I searched a little and found:

print long double on windows

maybe that is the explanation.

So I tried

long double x = 100.1;
cout << (double)x << endl;

which worked fine.

2nd EDIT:

Also see this link provided by Raphael

http://oldwiki.mingw.org/index.php/long%20double

Community
  • 1
  • 1
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • same result as with my original setprecision (0.01) – theresthatguy Apr 25 '15 at 06:10
  • @theresthatguy - hmmm... I just tested it and it appears that on my setup `cout`doesn't work correctly with `long double`. I tried `cout << (double)variableOfLongDoubleType << endl` and that works fine. But `cout << variableOfLongDoubleType << endl` fails and prints a small value - just like your example. Strange... I don't have a better solution than casting to double before cout. – Support Ukraine Apr 25 '15 at 06:26
  • See comments above about using fixed << setprecision(2) but it still outputs not the way I'd like. I did check the sizeof(long long) and it's 12 bytes for me. – theresthatguy Apr 25 '15 at 06:40
  • @neilsen, using double worked! I changed my print function to "<< fixed << setprecision(2) << double(x)" – theresthatguy Apr 25 '15 at 06:52
2

The default floating point presentation switches automatically between presentation like 314.15 and 3.1e2, depending on the size of the number and the maximum number of digits it can use. With this presentation the precision is the maximum number of digits. By default it's 6.

You can either increase the maximum number of digits so that your result can be presented like 314.15, or you can force such fixed point notation by using the std::fixed manipulator. With std::fixed the precision is the number of decimals.

However, with std::fixed very large and very small numbers may be pretty unreadable.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

The setprecision() manipulator specifies the number of digits after the decimal point. So, if you want 100.01 to be printed, use setprecision(2).

When you use setprecision(0.01), the value 0.01 is being converted to int, which will have a value of 0.

It wouldn't have hurt if you had actually read the documentation for setprecision() - that clearly specifies an int argument, not a floating point one.

Peter
  • 35,646
  • 4
  • 32
  • 74