5

I have recently become interested in learning about programming in c++, because I want to get a bit deeper understanding of the way computers work and handle instructions. I thought I would try out the data types, but I don't really understand what's happening with my output...

#include <iostream>
#include <iomanip>

using namespace std;

int main() {

    float fValue = 123.456789;
    cout << setprecision(20) << fixed << fValue << endl;
    cout << "Size of float: " << sizeof(float) << endl;

    double dValue = 123.456789;
    cout << setprecision(20) << fixed << dValue << endl;
    cout << "Size of double: " << sizeof(double) << endl;

    long double lValue = 123.456789;
    cout << setprecision(20) << fixed << lValue << endl;
    cout << "Size of long double: " << sizeof(long double) << endl;

    return 0;
}

The output I expected would be something like:

123.45678710937500000000
Size of float: 4
123.45678900000000000000
Size of double: 8
123.45678900000000000000
Size of long double: 16

This is my actual output:

123.45678710937500000000
Size of float: 4
123.45678900000000000000
Size of double: 8
-6518427077408613100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000000000000000000
Size of long double: 12

Any ideas on what happened would be much appreciated, thanks!

Edit:

System:
Windows 10 Pro Technical Preview
64-bit Operating System, x64-based processor
Eclipse CDT 8.5

MinGW Installation

Cyber Storm
  • 217
  • 1
  • 13
  • 1
    Can't reproduce. What compiler are you using? –  Feb 15 '15 at 07:26
  • 4
    The size of `long double` varies by compiler and hardware. Sizes 8, 12, and 16 are known. What you're seeing as a size is perfectly reasonable, even if it wasn't what you expected. The formatted output is not so reasonable, though. – Jonathan Leffler Feb 15 '15 at 07:27
  • FWIW (which is approximately nothing), running your code on Mac OS X 10.10.2 with GCC 4.9.1 yields: `123.45678710937500000000 Size of float: 4 123.45678900000000055570 Size of double: 8 123.45678900000000055570 Size of long double: 16`. Adding the `F` suffix to the `float` value and the `L` suffix to the `long double` value makes no difference to `float` or `double` output, but changes the `long double` output to: `123.45678900000000000059 Size of long double: 16`, which shows better accuracy. – Jonathan Leffler Feb 15 '15 at 07:34
  • @JonathanLeffler I would expect that the OP is on a 32-bit system, try `-m32`. –  Feb 15 '15 at 07:36
  • @remyabel I am running Windows 10, with Eclipse CDT 8.5.0 Luna – Cyber Storm Feb 15 '15 at 07:38
  • @remyabel: Curious why you think the OP is on a 32-bit system? – Drew Hall Feb 15 '15 at 07:38
  • @remyabel I am on a 64-bit system – Cyber Storm Feb 15 '15 at 07:39
  • @remyabel: Interesting thought, but it makes no difference on Mac OS X. I checked with `file longdbl` (the name of the testing program) and got the result `longdbl: Mach-O executable i386`, but it produced the same output as the 64-bit version. – Jonathan Leffler Feb 15 '15 at 07:39
  • Edited the info in my post, I hope that makes it more clear, let me know if more information is needed. – Cyber Storm Feb 15 '15 at 07:58
  • Cannot reproduce on Win64 with the MinGW 32 toolchain, with g++ version 4.7.1 – Kaslai Feb 15 '15 at 09:20
  • 1
    See http://stackoverflow.com/a/7136886/12711 for some details on what you're probably running into. tl;dr version: MinGW GCC uses a different binary type than the msvcrt runtime that MinGW relies on. This has been fixed in more recent versions of MinGW, but I don't know the details of the exact versions/distributions that have fixed the problem. – Michael Burr May 23 '15 at 17:47

1 Answers1

6

From the patch that fixed this in earlier versions:

MinGW uses the Microsoft runtime DLL msvcrt.dll. Here lies a problem: while gcc creates 80 bits long doubles, the MS runtime accepts 64 bit long doubles only.

This bug happens to me when I use 4.8.1 revision 4 from MinGW-get (the most recent version it offers), but not when I use 4.8.1 revision 5.

So you are not using long double wrong (although there would be better accuracy to do long double lValue = 123.456789L to make sure it doesn't take 123.456789 as a double, then cast it to a long double).

The easiest way to fix this would be to simply change the version of MinGW you are using to 4.9 or 4.7, depending on what you need (you can get 4.9 here).

If you are willing to instead use printf, you could change to printf("%Lf", ...), and either:

  • add the flag -posix when you compile with g++
  • add #define __USE_MINGW_ANSI_STDIO 1 before #include <cstdio> (found this from the origional patch)

Finally, you can even just cast to a double whenever you try to print out the long double (there is some loss of accuracy, but it shouldn't matter when just printing out numbers).

To find more details, you can also look at my blog post on this issue.

Update: If you want to continue to use Mingw 4.8, you can also just download a different distribution of Mignw, which didn't have that problem for me.

Morgan Redshaw
  • 153
  • 1
  • 8