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: 5
Enter its power: 3
5.000000 to the power of 0.000000 = 0.000000
7 ^ 3 = 343.000000
4.73 ^ 12 = 125410439.217423
32.01 ^ 1.54 = 208.036691
The 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: 5
Enter its power: 3
5.000000 to the power of 3.000000 = 125.000000
7 ^ 3 = 343.000000
4.73 ^ 12 = 125410439.217423
32.01 ^ 1.54 = 208.036691
I 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: 5
Enter its power: 3
5.000000 to the power of 0.000000 = 0.000000
7 ^ 3 = 343.000000
4.73 ^ 12 = 125410439.217423
32.01 ^ 1.54 = 208.036691
If I use the compiler from Visual Studio 2008 C++, this is the result:
Enter a number: 5
Enter its power: 3
5.000000 to the power of 3.000000 = 125.000000
7 ^ 3 = 343.000000
4.73 ^ 12 = 125410439.217423
32.01 ^ 1.54 = 208.036691
The 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 3
5.00 to the power of 0.00 = 0.00
7 ^ 3 = 343.00
4.73 ^ 12 = 125410439.22
32.01 ^ 1.54 = 208.04
And 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: 5
Enter a number: 3
5.00 to the (long double)power of 0.00 = 0.00
7 ^ 3 = 343.00
4.73 ^ 12 = 125410439.22
32.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.718282
Using 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.7182818284590452353602874713526624977572470936999595749669131
We 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 -lgmp
This 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 precision
double value using GMP and MPFR libraries.
Enter first number:
3.2
Enter second number:
5.4
Number 1: 3.1999999999999999999999999999999999999999999999999999999999980
Number 2: 5.3999999999999999999999999999999999999999999999999999999999960
Sum : 8.5999999999999999999999999999999999999999999999999999999999940
The 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!