First I actually thought there was something wrong with my programming skills. But after I compiled the same code using Visual Studio, it worked. So here's the code that doesn't seem to be working right with gcc compilers, but they do compile.
#include <stdio.h>#include <math.h>int main(){ long double r = 0; long double p = 0; printf ("Enter a number: "); scanf ("%lf", &r); printf ("Enter its power: "); scanf ("%lf", &p); printf ("%lf to the power of %lf = %lf\n", r, p, pow(r, p)); printf ("7 ^ 3 = %lf\n", pow (7.0,3.0)); printf ("4.73 ^ 12 = %lf\n", pow (4.73,12.0)); printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54)); return 0;}This is the first one. It compiles with GCC but the output doesn't seem to be what I'm expecting. (MinGW gcc (GCC) 4.5.1)
Enter a number: 5Enter its power: 35.000000 to the power of 0.000000 = 0.0000007 ^ 3 = 343.0000004.73 ^ 12 = 125410439.21742332.01 ^ 1.54 = 208.036691The part where I highlighted red doesn't seem to be right. But on the other hand, when I compiled it using Visual Studio, it worked very well.
Enter a number: 5Enter its power: 35.000000 to the power of 3.000000 = 125.0000007 ^ 3 = 343.0000004.73 ^ 12 = 125410439.21742332.01 ^ 1.54 = 208.036691I looked for a solution in the internet and I found sscanf. I tried to modified the code, it still compiles with gcc but yielding the same results.
#include <stdio.h>#include <math.h>int main(){ char line[100]; long double r = 0; long double p = 0; printf ("Enter a number: "); fgets(line,sizeof(line),stdin); sscanf(line,"%lf",&r); printf ("Enter its power: "); fgets(line,sizeof(line),stdin); sscanf(line,"%lf",&p); printf ("%lf to the power of %lf = %lf\n", r, p, pow(r, p)); printf ("7 ^ 3 = %lf\n", pow (7.0,3.0)); printf ("4.73 ^ 12 = %lf\n", pow (4.73,12.0)); printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54)); return 0;}Using the gcc compiler of MinGW this is the result: (MinGW gcc (GCC) 4.5.1)
Enter a number: 5Enter its power: 35.000000 to the power of 0.000000 = 0.0000007 ^ 3 = 343.0000004.73 ^ 12 = 125410439.21742332.01 ^ 1.54 = 208.036691If I use the compiler from Visual Studio 2008 C++, this is the result:
Enter a number: 5Enter its power: 35.000000 to the power of 3.000000 = 125.0000007 ^ 3 = 343.0000004.73 ^ 12 = 125410439.21742332.01 ^ 1.54 = 208.036691The results are still woefully erroneous. Currently, I don't understand why this is happening. The gcc i'm using is the one I downloaded from MinGW, the same also happens with the gcc from Cygwin. Is there something wrong with my code or is this a bug? The MinGW is gcc (GCC) 4.5.1, while the one in Cygwin is gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125). The only one that compiles the code as I expected is the compiler from Visual Studio C++ 2008.
I have raised this question to Bytes, LinuxForums, CBoard, CodeCall, DreamInCode, ProgrammingForums. Finally, after having a stroll around the internet, and thanks to the help from the different people on the aforesaid forums. I was able to uncover a lot of issues. First, I'll discuss about the following code which according to my tests, works on Cygwin GCC 3.4.4 and VSC++. But do notice that I've changed lf to Lf because this is the right way to address a long double.
math_typecasted_withgetchar.c
#include <stdio.h>#include <math.h>int main(){ // my personal troubles with long double // while using gcc under cygwin and mingw long double r = 0; long double p = 0; long double a = 0; //printf ("Enter a number <space> power: "); //scanf( "%lf %lf", &r, &p ); printf ("Enter a number: ");scanf( "%Lf", &r);
printf ("Enter a number: ");getchar();
scanf( "%Lf", &p );
// r to the power of p a = pow(r,p); // put (long double) typecast before (long double)pow if you're // printing (long double)pow directly on printf and you're using // Cygwin's gcc (GCC) 3.4.4. You may not edit this // code if you're compiling on VSC++ or MinGW's gcc // (GCC) 4.5.1 printf ("%.2Lf to the power of %.2Lf = %.2Lf\n", r, p, a); printf ("7 ^ 3 = %.2Lf\n", (long double)pow(7.0,3.0)); printf ("4.73 ^ 12 = %.2Lf\n", (long double)pow(4.73,12.0)); printf ("32.01 ^ 1.54 = %.2Lf\n", (long double)pow(32.01,1.54)); return 0;}The next code works with MinGW with GCC gcc (GCC) 4.5.1:
math_getchar.c
#include <stdio.h>#include <math.h>int main(){ // my personal troubles with long double // while using gcc under cygwin and mingw long double r = 0; long double p = 0; long double a = 0; //printf ("Enter a number <space> power: "); //scanf( "%lf %lf", &r, &p ); printf ("Enter a number: ");scanf( "%Lf", &r);
printf ("Enter a number: ");getchar();
scanf( "%Lf", &p );
// r to the power of p a = pow(r,p); // put (long double) typecast before (long double)pow if you're // printing (long double)pow directly on printf and you're using // Cygwin's gcc (GCC) 3.4.4. You may not edit this // code if you're compiling on VSC++ or MinGW's gcc // (GCC) 4.5.1 printf ("%.2Lf to the power of %.2Lf = %.2Lf\n", r, p, a); printf ("7 ^ 3 = %.2Lf\n", pow(7.0,3.0)); printf ("4.73 ^ 12 = %.2Lf\n", pow(4.73,12.0)); printf ("32.01 ^ 1.54 = %.2Lf\n", pow(32.01,1.54)); return 0;}On gcc 4.5.1, there doesn't seem to be any typecast necessary to compile it, while it is necessary for direct printf of pow value from gcc 3.4.4. And in order to solve the issue with the scanf(), I find this reply from a webmaster of a certain website very helpful.
Allex Allain to Me
Hi Bangon, the problem is almost certainly related to a difference between GCC and MSVC in how it processes scanf -- sscanf and scanf do basically the same thing, from different sources, so it doesn't surprise me that neither one works on GCC and both work on MSVC.
I'm guessing that scanf in GCC is keeping the space in the keyboard buffer. You can tell that something is wrong b/c the second input is always 0. You might trying using scanf to read in both numbers on the same line:
scanf( "%lf %lf", &r, &p );
separated by a space.
Alex
http://www.cprogramming.com - Your Resource for C and C++
Follow me on twitter at http://twitter.com/alexallain
On Facebook, http://www.facebook.com/cprogrammingcom
Join the mailing list at http://www.cprogramming.com/mailing.html
Using the CygWin's gcc 3.4.4 when modifying the code to use the following, it works very well:
printf ("Enter a number <space> power: ");scanf( "%Lf %Lf", &r, &p );But for MinGW's gcc 4.5.1 when the code is modified with the same modifications, it doesn't work very well with the following output:
Enter a number <space> power: 5 35.00 to the power of 0.00 = 0.007 ^ 3 = 343.004.73 ^ 12 = 125410439.2232.01 ^ 1.54 = 208.04And yes it does solve the problems temporarily for CygWin's gcc 3.4.4. However I looked-up the keyboard buffer issue on Google. And I found out an interesting way to circumvent this issue. By inputting a getchar() function in the middle, as shown from the two codes above (math_getchar.c and math_typecasted_getchar.c), for MSVC++ and GCC 3.4.4, I can successfully read two long double values on separate scanf()'s. However, on MinGW's gcc 4.5.1, this doesn't seem to be the case and the problem persists. Hence math_getchar.c although it compiles with gcc 4.5.1, it does not work as expected.
Giving the same results as before:
Enter a number: 5Enter a number: 35.00 to the (long double)power of 0.00 = 0.007 ^ 3 = 343.004.73 ^ 12 = 125410439.2232.01 ^ 1.54 = 208.04
And finally, I think this article explains things very clearly. Following is a quote from the article:
After months of experimentation, I have settled on MinGW/MSYS as the best development environment for my purposes. Its advantages include the following:
Full support (for internal calculations) of 80-bit long doubles (including transcendentals) and 64-bit integers; note, however, that the printf/scanf family produces erroneous results for long doubles, and uses peculiar syntax for 64-bit integers.
Disadvantages of the MinGW/MSYS environment include the following:
The printf/scanf family of functions is unable to correctly handle the 80-bit long double floating point variables native to the x86 Intel processors and FPUs (and compatible processors, such as AMD). Either the value must be cast to double and printed, with resulting loss of precision (16 digits rather than 19), or a custom function must be employed for the purpose.
For my case, I am only experiencing these problems because I'm using Cygwin and MinGW gcc versions when testing my code. But I were using a real Linux or Unix distribution then I would not likely get this weired error. And yes I think this is a bug, and very clearly needs fixing. Since they're offering long double datatype, they should at least make scanf and printf work with it. Anyway, thanks for the follow up.
And also, I found out the most efficient solution for my problem which is requiring very high precision mathematical calculations as suggested by the article. By using GMP 4.3.1 and MPFR 2.4.1 I was able to use very high precision datatypes from its libraries without problems with printf() and scanf(). I am posting an example below.
In this example, let us consider the following mathematical series equation:
ex = SUMMATION((xn)/n!) n=0 TO +INF ex = x0/0! + x1/1! + x2/2! + x3/3! + x4/4! + x5/5! + ... + xn/(n)! + ...
Let us solve the value of e1 or basically e with accuracy of up to n=100 using the power series equation above. Hence the resulting series equation would be x=1 (in your calculator this should be e or e1):
e1 = SUMMATION((1n)/n!) n=0 TO 100 e1 = 10/0! + 11/1! + 12/2! + 13/3! + 14/4! + 15/5! + ... + 1100/100!
e1 = 1 + 1 + 1/2 + 1/3! + 1/4! + 1/5! + ... + 1/100!
Using the Standard Input Output (stdio.h) Library:
(Toggle Plain Text)#include <stdio.h>int main (void){ unsigned int i; double s, t, u; t = 1; s = 1; u = 1; for (i = 1; i <= 100; i++) { t = t * i; u = 1; u = u / t; s = s + u; } printf ("Sum is %lf \n", s); return 0;}Output with gcc 3.4.4:
Sum is 2.718282Using the GMP 4.3.1 and MPFR 2.4.1 Libraries:
#include <stdio.h>#include <gmp.h>#include <mpfr.h>int main (void){ unsigned int i; mpfr_t s, t, u; mpfr_init2 (t, 200); mpfr_set_d (t, 1.0, GMP_RNDD); mpfr_init2 (s, 200); mpfr_set_d (s, 1.0, GMP_RNDD); mpfr_init2 (u, 200); for (i = 1; i <= 100; i++) { mpfr_mul_ui (t, t, i, GMP_RNDU); mpfr_set_d (u, 1.0, GMP_RNDD); mpfr_div (u, u, t, GMP_RNDD); mpfr_add (s, s, u, GMP_RNDD); } printf ("Sum is "); mpfr_out_str (stdout, 10, 0, s, GMP_RNDD); putchar ('\n'); mpfr_clear (s); mpfr_clear (t); mpfr_clear (u); return 0;}Output with gcc 3.4.4:
Sum is 2.7182818284590452353602874713526624977572470936999595749669131We can observe the sheer precision with 200 bit representation of double in this case compared to the standard double as shown in the first result from the first code. Anyway, as a side note, My Casio FX-991ES calculator can do up to 2.718281828. :)
I tried everything under Cygwin. But do note that you'll need to have the GMP ang MPFR libraries added during the setup of Cygwin. Finally in order to compile the second code (the one using GMP and MPFR), if you've already installed GMP and MPFR use the following command:
gcc mpfr_sample.c -o mprfr_sample.exe -lmpfr -lgmpThis next example will show how reading values from stdin works. And there are no problems encountered when reading multiple inputs with this one. And I believe this is the best part!
#include <stdio.h>#include <gmp.h>#include <mpfr.h>int main (void){ // Declaration of variables to be used unsigned int i; mpfr_t s, t, u; // Initialization of High Precision // long doubles of up to 200bit // accuracy. mpfr_init2 (t, 200); mpfr_set_d (t, 1.0, GMP_RNDD);
mpfr_init2 (s, 200); mpfr_set_d (s, 1.0, GMP_RNDD);
mpfr_init2 (u, 200); mpfr_set_d (u, 1.0, GMP_RNDD); printf ("This program will ask for two numbers. It will \n"); printf ("then initialize them in to a 200bit high precision\n"); printf ("double value using GMP and MPFR libraries. \n\n"); printf ("Enter first number: \n"); // scanf process with error detection if (mpfr_inp_str(s, stdin, 10, GMP_RNDD)==0) printf ("Error encountered while reading number.\n");
printf ("Enter second number: \n"); if (mpfr_inp_str(t, stdin, 10, GMP_RNDD)==0) printf ("Error encountered while reading number.\n"); // printf process printf ("Number 1: "); mpfr_out_str (stdout, 10, 0, s, GMP_RNDD); putchar ('\n');
printf ("Number 2: " ); mpfr_out_str (stdout, 10, 0, t, GMP_RNDD); putchar ('\n'); // Arithmetic process (addition) mpfr_add (u, s, t, GMP_RNDD); printf ("Sum : "); mpfr_out_str (stdout, 10, 0, u, GMP_RNDD); putchar ('\n'); // Garbage collection.
mpfr_clear (s); mpfr_clear (t); mpfr_clear (u); return 0;}Output:
This program will ask for two numbers. It will then initialize them in to a 200bit high precisiondouble value using GMP and MPFR libraries. Enter first number: 3.2Enter second number: 5.4Number 1: 3.1999999999999999999999999999999999999999999999999999999999980Number 2: 5.3999999999999999999999999999999999999999999999999999999999960Sum : 8.5999999999999999999999999999999999999999999999999999999999940The advantage for this library is it doesn't depend on the support of the compiler for certain datatypes. For example, in the above example, I used 200 bit precision double datatype to initialize my custom double value. Which basically means a very high precision double value as evidenced by my results. I can compile this same code using Visual Studio C++ and GCC without any problems, just add the include files and the required libraries. If you do this with the standard long double values, you'll get in to a lot of problems like I did in the first place which caused my to ask for help from this forum. You can use up to 256 bit high precision double value using this library. I hope this will help everyone who are doing precision arithmetic for scientific research. For more information regarding the libraries visit MPFR Main Website and for the sample. And Finally, a joyful and merry Christmas to all!