incorrect printf o/p for doubles

Y

Yogesh Khanolkar

Hi,

I am getting incorrect o/p from the code below:

#include<stdio.h>
#include<float.h>
#include<limits.h>
main()
{
double val,val1;
val=123456789012.123456;
val1=123456789012.123456;
val2=val*val1;
printf("%f\n",val2);
}

The result I get is 15241578753183967100000.000000 instead of the correct value.

I am running on HP-UX 11 with ansi c compiler.

Can anyone let me know why I am getting this result.
 
G

Glen Herrmannsfeldt

Yogesh Khanolkar said:
Hi,

I am getting incorrect o/p from the code below:

#include<stdio.h>
#include<float.h>
#include<limits.h>
main()
{
double val,val1;
val=123456789012.123456;
val1=123456789012.123456;
val2=val*val1;
printf("%f\n",val2);
}

The result I get is 15241578753183967100000.000000 instead of the correct value.

I am running on HP-UX 11 with ansi c compiler.

Can anyone let me know why I am getting this result.

It looks close enough for me. What answer did you expect?

-- glen
 
J

James Hu

#include<stdio.h>
#include<float.h>
#include<limits.h>
main()
{
double val,val1;
val=123456789012.123456;
val1=123456789012.123456;
val2=val*val1;
printf("%f\n",val2);
}

It looks like val2 is defaulting to an int type, and you are trying to
print it out like a double.

-- James
 
J

Jens.Toerring

Yogesh Khanolkar said:
I am getting incorrect o/p from the code below:
#include<stdio.h>
#include<float.h>
#include<limits.h>
main()
{
double val,val1;
val=123456789012.123456;
val1=123456789012.123456;
val2=val*val1;
printf("%f\n",val2);
}

This won't compile because 'val2' is never declared. Additional
problems are the missing 'int' in front of main() (you only get
away with this when you don't use a C99 compiler) and the
missing return statement at the end - main() always returns an int.
The result I get is 15241578753183967100000.000000 instead of the correct value.

That seems to the best approximation your machine is able to come up
with - floating point variables have only a finite precision. And 18
digits doesn't look too bad. Welcome to the wonderful world of
floating point math ;-) And since you're already including <float.h>
check how many digits the compiler is promising you by printing out
the value of DBL_DIG.
Regards, Jens
--
_ _____ _____
| ||_ _||_ _| (e-mail address removed)-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring
 
D

Dan Pop

In said:
Hi,

I am getting incorrect o/p from the code below:

#include<stdio.h>
#include<float.h>

What for?
#include<limits.h>

What for?
main()
{
double val,val1;
val=123456789012.123456;
val1=123456789012.123456;
val2=val*val1;
^^^^
Huh?!? I can't believe that your compiler didn't complain!
printf("%f\n",val2);
}

The result I get is 15241578753183967100000.000000 instead of the correct value.

HUGE clue: what is the "correct" value and why? Additional clue: make
sure to base your answer on the value of DBL_DIG as defined by your
implementation in <float.h>.

And next time, please post the actual code you have compiled.

Dan
 
W

Wolfgang Riedel

Glen said:
like: 15241578753183966898832.546185383936

maybe float/double is not the best bet, doing scientific/financial calculations.
There are libraries and other languages, which do this natively.
Look them up after you've learned C (others have told you the main-thing and
more).

Wolfgang
 
G

Glen Herrmannsfeldt

Wolfgang Riedel said:
(snip)
like: 15241578753183966898832.546185383936

maybe float/double is not the best bet, doing scientific/financial calculations.
There are libraries and other languages, which do this natively.
Look them up after you've learned C (others have told you the main-thing and
more).

Floating point was designed for, and works well for, scientific quantities
that have inherent uncertainty.

Possibly the most important constant for most people, Newton's G, is known
only to about four decimal digits. (That is what holds us down onto the
earth's surface.) For numbers with such relative uncertainty (relative to
the size of the number), especially when they can be very big or very small,
floating point is convenient and useful.

For numbers with absolute uncertainty (that doesn't depend on the size of
the number), such as financial or typesetting calculations, fixed point
values where the unit corresponds to the measuring unit in use, tend to give
better results.

The product above has 35 decimal digits, or about 112 bits of precision.
There are machines with floating point types that long, or close to that
long. If they are supported by C, they tend to be called long double.
(Some CDC machines came close with double, but I don't know of any are still
running.)

Otherwise, the usual implementation of float has six or seven digits of
precision, and double about 16.

-- glen
 
M

Martin Ambuhl

Yogesh said:
Hi,

I am getting incorrect o/p from the code below:

#include<stdio.h>
#include<float.h>
#include<limits.h>
main()
{
double val,val1;
val=123456789012.123456;
val1=123456789012.123456;
val2=val*val1;

ERROR! val2 never declared.
printf("%f\n",val2);
}

The result I get is 15241578753183967100000.000000 instead of the correct value.

The real mysteries are
(1) what your real code is, since yours doesn't compile, and
(2) what you might have been expecting.
Run the code below and see what your implementation gives you.
FLT_DIG may be as small as 6, and DBL_DIG and LDBL_DIG as small as 10.
Your assignment statements assume DBL_DIG to be 18 and the "right" answer
requires DBL_DIG to be at least 35. I doubt the you machine really has
doubles of more than 40 octets.

#include<stdio.h>
#include<float.h>

int main(void)
{
float f1 = 123456789012.123456, f2;
double d1 = 123456789012.123456f, d2;
long double ld1 = 123456789012.123456L, ld2;
f2 = f1 * f1;
printf("float: %.*g squared is %.*g\n", FLT_DIG, f1, FLT_DIG, f2);
d2 = d1 * d1;
printf("double: %.*g squared is %.*g\n", DBL_DIG, d1, DBL_DIG, d2);
ld2 = ld1 * ld1;
printf("long double: %.*Lg squared is %.*Lg\n", LDBL_DIG, ld1,
LDBL_DIG, ld2);
return 0;
}


float: 1.23457e+11 squared is 1.52416e+22
double: 123456790528 squared is 1.52415791274745e+22
long double: 123456789012.123456 squared is 1.52415787531839669e+22
 
Y

Yogesh Khanolkar

Martin Ambuhl said:
ERROR! val2 never declared.


The real mysteries are
(1) what your real code is, since yours doesn't compile, and
(2) what you might have been expecting.
Run the code below and see what your implementation gives you.
FLT_DIG may be as small as 6, and DBL_DIG and LDBL_DIG as small as 10.
Your assignment statements assume DBL_DIG to be 18 and the "right" answer
requires DBL_DIG to be at least 35. I doubt the you machine really has
doubles of more than 40 octets.

#include<stdio.h>
#include<float.h>

int main(void)
{
float f1 = 123456789012.123456, f2;
double d1 = 123456789012.123456f, d2;
long double ld1 = 123456789012.123456L, ld2;
f2 = f1 * f1;
printf("float: %.*g squared is %.*g\n", FLT_DIG, f1, FLT_DIG, f2);
d2 = d1 * d1;
printf("double: %.*g squared is %.*g\n", DBL_DIG, d1, DBL_DIG, d2);
ld2 = ld1 * ld1;
printf("long double: %.*Lg squared is %.*Lg\n", LDBL_DIG, ld1,
LDBL_DIG, ld2);
return 0;
}


float: 1.23457e+11 squared is 1.52416e+22
double: 123456790528 squared is 1.52415791274745e+22
long double: 123456789012.123456 squared is 1.52415787531839669e+22

I am extermely sorry for posting incorrect code. I forgot to paste the
val2 declaration of double.
 
K

Keith Thompson

James Hu said:
It looks like val2 is defaulting to an int type, and you are trying to
print it out like a double.

Undeclared variables don't default to int. Some compilers, especially
old ones, might let you get away with

val2;

as a declaration for val2 with a default type of int, but it's never
been possible to omit the declaration altogether.
 
J

James Hu

Keith Thompson said:
Undeclared variables don't default to int. Some compilers, especially
old ones, might let you get away with

val2;

as a declaration for val2 with a default type of int, but it's never
been possible to omit the declaration altogether.

Crikes! Thanks for the correction.

-- James
 
J

Jarno A Wuolijoki

Undeclared variables don't default to int. Some compilers, especially
old ones, might let you get away with

val2;

as a declaration for val2 with a default type of int, but it's never
been possible to omit the declaration altogether.

Never in standard C at least, but where does this odd interpretation
come from then? Did K&R allow it or is it just some awfully widespread
hack?
 
J

James Hu

Never in standard C at least, but where does this odd interpretation
come from then? Did K&R allow it or is it just some awfully widespread
hack?

Many pre-ANSI C compilers supported a syntax along the lines of:

var;

to declare a global integer variable. It also supported a syntax of

foo(var)
var; /* this line is optional */
{
/* ... */
}

to declare an integer parameter. (As an aside, gcc still accepts
the above syntax.)

I incorrectly assumed pre-ANSI C compilers allowed the implicit
declaration of an integer variable, similar to the way pre-ANSI C
and C90 do for a function returning int.

-- James
 
D

Dan Pop

In said:
Undeclared variables don't default to int. Some compilers, especially
old ones, might let you get away with

val2;

as a declaration for val2 with a default type of int, but it's never
been possible to omit the declaration altogether.

And that is/was allowed at file scope only, because at block scope this
looks like an expression statement with an undeclared identifier.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top