[comp.lang.c] log10

elzea@sersun0.essex.ac.uk (El-Zein A A) (02/26/90)

	My calculator gives me 0.9030899 for log(8),

	While the following code (which I thought would
	
	give me the above value of 0.9030899) prints 
	
	-312.770165.

	.
	.
	.
	.
	double l;
	.
	.
	l = log10(8);
	printf("%f", l);
        .
	.
	.


	Can anybody tell me why.


			thanks in advance,

			Mustapha;

ping@cubmol.bio.columbia.edu (Shiping Zhang) (02/26/90)

In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
 
>	My calculator gives me 0.9030899 for log(8),
>	While the following code (which I thought would
>	give me the above value of 0.9030899) prints 
>	-312.770165.
 	.
>	double l;

>	l = log10(8);
>	printf("%f", l);
 
>	Can anybody tell me why.

log10() expects a double as its argument. So use 8.0 instead of 8.

-ping

karl@haddock.ima.isc.com (Karl Heuer) (02/26/90)

In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
>My calculator gives me 0.9030899 for log(8), While the [elided] code prints
>-312.770165.  Can anybody tell me why.

Yes.  The program `lint' can tell you why.

If you don't have lint, or the equivalent functionality via compiler options,
then your vendor sold you only half a C compiler.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

grisanti@plains.UUCP (Ames Grisanti) (02/26/90)

Newsgroups: /usr/spool/news/comp/lang/c/26450
Subject: log10(8);
Reply-To: grisanti@plains.UUCP (Ames Grisanti)
Organization: UND Energy Research Center

You must make the following changes:

	double log10();

	l = log10(8.0);

If you do this you will get the correct answer.


Ames Grisanti
[grisanti@plains.NoDak.edu      --         Internet]
[grisanti@plains or ndsuvax     --         Bitnet  ]
[uunet!plains!grisanti          --         UUCP    ]

darcy@druid.uucp (D'Arcy J.M. Cain) (02/26/90)

In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
       [With those stupid extra line removed so we don't have to chase
        through multiple screens to see the question!]
>	My calculator gives me 0.9030899 for log(8),
>	While the following code (which I thought would
>	give me the above value of 0.9030899) prints 
>	-312.770165.
>  [...]
>	double l;
>  [...]
>	l = log10(8);
>	printf("%f", l);
>
>	Can anybody tell me why.

I tried the following code using gcc


#include <math.h>
#include <stdio.h>

int main(void)
{
	double l;

	l = log10(8);
	printf("%lf\n", l);
}

And I got the same result as you.  I then made the following changes

[...]
	double l = 8.0;
[...]
	l = log10(l);

and I got the correct answer.  This tells me that I haven't finished
prototyping all of the functions.  In particular the function declaration
in math.h reads:
    double log10();
which is the normal sort of function declaration in pre-ANSI C.  The
following:
    double log10(double x);
as a prototype with ANSI C caused my first version to give the correct result.

With a pre-ANSI C compiler I guess you would have to do the following:
    l = log10((double)(8.0);

I like it in the include file because I'm basically lazy.

-- 
D'Arcy J.M. Cain (darcy@druid)     |   Thank goodness we don't get all 
D'Arcy Cain Consulting             |   the government we pay for.
West Hill, Ontario, Canada         |
(416) 281-6094                     |

harlow@plains.UUCP (Jay B. Harlow) (02/27/90)

In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
>
>	double l;
>	.
>	l = log10(8);
		  ^  this is a integer!
>	printf("%f", l);
>

simple, (is this a trick question? ;-))

because the 8 you sent as an argument to log10 is a integer, if you did not
include math.h (where log10 is declared) log10 would return a '0.00000' 
(mine does ;-)  Any way because your compiler does not have a PROTOTYPE 
(YEA ANSI C) it is not smart enough to convert the integer 8 to
a double (8.0) which is what log10 expects. 
You do realize that a integer 8 is almost never the same binary format
(as an argument to a function) as a double is? so log10 was
reading extra stack stuff as a floating point number.

			Jay
-- 
		Jay B. Harlow	<harlow@plains.nodak.edu>
	uunet!plains!harlow (UUCP)	harlow@plains (Bitnet)

Of course the above is personal opinion, And has no bearing on reality...

amull@Morgan.COM (Andrew P. Mullhaupt) (02/27/90)

In article <16022@haddock.ima.isc.com>, karl@haddock.ima.isc.com (Karl Heuer) writes:
> In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
> >My calculator gives me 0.9030899 for log(8), While the [elided] code prints
> >-312.770165.  Can anybody tell me why.
> 
> Yes.  The program `lint' can tell you why.

lint might not tell him about the tragedy unless he uses

lint filename.c -lm

as opposed to

lint filename.c

which will not necessarily complain. You have to put lint in the 
picture about linking or this particular error could easily be
missed.

Later,
Andrew Mullhaupt

CMH117@psuvm.psu.edu (Charles Hannum) (02/27/90)

In article <1990Feb26.031254.11354@cubmol.bio.columbia.edu>,
ping@cubmol.bio.columbia.edu (Shiping Zhang) says:
>
>In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A)
>writes:
>
>>       My calculator gives me 0.9030899 for log(8),
>>       While the following code (which I thought would
>>       give me the above value of 0.9030899) prints
>>       -312.770165.
>        .
>>       double l;
>
>>       l = log10(8);
>>       printf("%f", l);
>
>>       Can anybody tell me why.

>log10() expects a double as its argument. So use 8.0 instead of 8.
>
You may also have to change the printf() to:

   printf("%lf", l);


Virtually,
- Charles Martin Hannum II       "Klein bottle for sale ... inquire within."
    (That's Charles to you!)     "To life immortal!"
  cmh117@psuvm.{bitnet,psu.edu}  "No noozzzz izzz netzzzsnoozzzzz..."
  c9h@psuecl.{bitnet,psu.edu}    "Mem'ry, all alone in the moonlight ..."

karl@haddock.ima.isc.com (Karl Heuer) (02/27/90)

In article <90057.130433CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes:
>You may also have to change the printf() to:
>   printf("%lf", l);

No.  "%f" is the correct printf format for double; "%lf" is undefined.
Backward compatibility strikes again.

(In an ideal world, the three floating-point sizes would be called "short
float", "float", and "long float", and their printf/scanf formats would be
"%hf", "%f", and "%lf".  Unfortunately, for historical reasons the types are
"float", "double", and "long double", their scanf formats are "%f", "%lf", and
"%Lf", and their printf formats are <none>, "%f", and "%Lf".  There is no
printf format for float, since one cannot directly pass floats by value to a
variadic function.)

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

raw@math.arizona.edu (Rich Walters) (02/27/90)

In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
>
>	My calculator gives me 0.9030899 for log(8),
>	While the following code (which I thought would
>	give me the above value of 0.9030899) prints 
>	-312.770165.
>
>	double l;
>	.
>	l = log10(8);
>	printf("%f", l);
>       .
>
>	Can anybody tell me why.
>

Try printf"%lf",l);  after all l is declared to be a double!!!!!!!!



					Richard Walter



-------------------------------------------------------------------------------

			Keep on crunching those numbers

-------------------------------------------------------------------------------

meissner@osf.org (Michael Meissner) (02/27/90)

In article <1460@amethyst.math.arizona.edu> raw@math.arizona.edu (Rich
Walters) writes:

| In article <3244@servax0.essex.ac.uk> elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
| >
| >	My calculator gives me 0.9030899 for log(8),
| >	While the following code (which I thought would
| >	give me the above value of 0.9030899) prints 
| >	-312.770165.
| >
| >	double l;
| >	.
| >	l = log10(8);
| >	printf("%f", l);
| >       .
| >
| >	Can anybody tell me why.
| >
| 
| Try printf"%lf",l);  after all l is declared to be a double!!!!!!!!

Sigh.  Printf is a varargs function.  This means that there is no way
a 'float' can be passed to it.  Thus %f and %lf are synomous.....
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA

Catproof is an oxymoron, Childproof is nearly so

CMH117@psuvm.psu.edu (Charles Hannum) (02/28/90)

In article <MEISSNER.90Feb27104552@curley.osf.org>, meissner@osf.org (Michael
Meissner) says:
>
>| Try printf"%lf",l);  after all l is declared to be a double!!!!!!!!
>
>Sigh.  Printf is a varargs function.  This means that there is no way
>a 'float' can be passed to it.  Thus %f and %lf are synomous.....

As I don't have access to my copy of K&R2 until Monday, could you please point
me to a specific reference?

BTW:  I know of at least one compiler that *does* pass floats as floats, not
      doubles.


Virtually,
- Charles Martin Hannum II       "Klein bottle for sale ... inquire within."
    (That's Charles to you!)     "To life immortal!"
  cmh117@psuvm.{bitnet,psu.edu}  "No noozzzz izzz netzzzsnoozzzzz..."
  c9h@psuecl.{bitnet,psu.edu}    "Mem'ry, all alone in the moonlight ..."

puh@grumpy.sarnoff.com (Patrick U. Hsieh x3145) (02/28/90)

Try using

	l = log10(8.0);

instead of

	l = log10(8);

Works for me!

Patrick Hsieh
David Sarnoff Research Center

puh@filbert.sarnoff.com

karl@haddock.ima.isc.com (Karl Heuer) (02/28/90)

In article <756@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
>lint might not tell him about the tragedy unless he [specifies -lm]

True (as Mark Brader also pointed out).  But (a) in that case he'd still get a
warning `log10 used but not defined', which is a clue, and (b) in order to get
this far he has to already know about `cc -lm', and it doesn't take too much
imagination to guess that lint requires the same magic as cc.  (Similarly for
any -D flags.)

Karl W. Z. Heuer (karl@ima.ima.is.ccom or harvard!ima!karl), The Walking Lint

ted@welch.jhu.edu (Ted Ying) (02/28/90)

In article <292@grumpy.sarnoff.com> puh@grumpy.sarnoff.com (Patrick U. Hsieh   x3145) writes:
>Try using
>
>	l = log10(8.0);
>
>instead of
>
>	l = log10(8);
>
>Works for me!
>
>Patrick Hsieh
>David Sarnoff Research Center
>
>puh@filbert.sarnoff.com

darcy@druid.uucp (D'Arcy J.M. Cain) (03/01/90)

In article <90058.153054CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes:
>In article <MEISSNER.90Feb27104552@curley.osf.org>, meissner@osf.org (Michael
>Meissner) says:
>>
>>| Try printf"%lf",l);  after all l is declared to be a double!!!!!!!!
>>
>>Sigh.  Printf is a varargs function.  This means that there is no way
>>a 'float' can be passed to it.  Thus %f and %lf are synomous.....
>
>As I don't have access to my copy of K&R2 until Monday, could you please point
>me to a specific reference?
>
That is true for the following code:

...
int foo(float x, double y);
...
   foo(3, 4);

In this case 3 is passed as a float and 4 is passed as a double.  In the
case of printf the prototype doesn't specify the types of the argument
list (specified with ellipsis notation to show variable arguments) and
therefore "... suffer default argument promotion ..." (K&R2 pp.202).

>BTW:  I know of at least one compiler that *does* pass floats as floats, not
>      doubles.
>
That compiler is broke if it passes floats to printf.

-- 
D'Arcy J.M. Cain (darcy@druid)     |   Thank goodness we don't get all 
D'Arcy Cain Consulting             |   the government we pay for.
West Hill, Ontario, Canada         |
(416) 281-6094                     |

asd@cbnewsj.ATT.COM (Adam S. Denton) (03/01/90)

In article <90058.153054CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes:
>
>In article <MEISSNER.90Feb27104552@curley.osf.org>, meissner@osf.org (Michael
>Meissner) says:
>>
>>| Try printf"%lf",l);  after all l is declared to be a double!!!!!!!!
>
>>Sigh.  Printf is a varargs function.  This means that there is no way
>>a 'float' can be passed to it.  Thus %f and %lf are synomous.....
>
>As I don't have access to my copy of K&R2 until Monday, could you please point
>me to a specific reference?
>
>BTW:  I know of at least one compiler that *does* pass floats as floats, not
>      doubles.
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

I question this.  IMHO there is no way you could ever find this out, unless you
have looked at the assembly-language code emitted by your compiler.

If your compiler is non-ANSI (i.e. K&R1/UNIX vintage), then floats can NEVER
be passed to functions, though they might appear to.  For example,

   void floatfun(arg)
   float arg;
   { ... }

   main()
   {
     float value;
     value = 1.0;
     floatfun(value);
     ...
   }

What happens in main() is that value is converted (as if by cast) to
type 'double', then transmitted as a double to floatfun().
The code for floatfun will contain a routine to convert its argument from
'double' to 'float' as soon as floatfun() is entered.

Although this might seem silly, it is in fact what happens.  If you
dig up a K&R1, you will find that this behavior is explicitly blessed.

If you have an ANSI compiler, then the same thing happens (floats are
automatically converted to double when passed to functions),
EXCEPT that it is possible to circumvent this conversion under two conditions:
  1) A *complete* prototype of the function is in effect when the call
     to the function is compiled; and
  2) The function is declared explicitly with a 'float' type argument
     in its argument list (between the parentheses).
For example,

  void floatfun(float arg);

  main()
  {
    floatfun(2.0);
  }

will pass 2.0 to floatfun as a float.  (Incidentally, one could write 2.0F
to explicitly show that 2.0 is a float constant, not double...)

...printf(), however, does not meet condition (2) above.  The declaration
for printf() is
   void printf(char *s, ...)
  (^^^^ I think)
which does *not* contain the explicit type `float' in the argument list;
therefore, all floats will be converted to double when it is called.

It is possible, also, that float and double have EXACTLY THE SAME PRECISION
on your machine/compiler.  Never was it said (in K&R) or standardized that
`double' must have greater precision than `float.'  Maybe that's what
you're observing...

Also, I don't believe that "%lf" is blessed by the ANSI standard in
...printf(), although the Turbo-C guide does mention it, interestingly.
The correct way to output floats (actually, doubles) is "%f".
However, "%lf" is of course necessary for scanf()...

Hope this cleared things up a little.

Adam
asd@mtqua.att.com

amull@Morgan.COM (Andrew P. Mullhaupt) (03/02/90)

In article <16048@haddock.ima.isc.com>, karl@haddock.ima.isc.com (Karl Heuer) writes:
> In article <756@s5.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
> >lint might not tell him about the tragedy unless he [specifies -lm]
> 
> True (as Mark Brader also pointed out).  But (a) in that case he'd still get a
> warning `log10 used but not defined', which is a clue, and (b) in order to get
No. This did not happen when I used lint on Sun OS 4.??. Is this lint
broken because it knows about log10 without the -lm flag? The compiler,
(as one would expect) did need the -lm directive.

> this far he has to already know about `cc -lm', and it doesn't take too much
> imagination to guess that lint requires the same magic as cc.  (Similarly for
> any -D flags.)
> 
> Karl W. Z. Heuer (karl@ima.ima.is.ccom or harvard!ima!karl), The Walking Lint
I would expect that a certain translation of gestalt is required in order
to reconcile what seems obvious to 'The Walking Lint' as opposed to the
guy who originally had the difficulty. In fact, another tool which works
out compiler source dependencies - cscope - doesn't have the same command
line arguments as cc. This fact places different burdens, I would suppose
on different people's imaginations. It is my experience that C is not a
very easy language if you seriously use three or four others across more
than two operating systems, and it's very common to have deep mysteries
arise out of thinking in the wrong context. You may suppose that it adds
little help to be explicit about the -lm flag, but I believe that the
answer should be as complete as possible. Who knows - somebody using
Sun OS might encounter this difficulty. Sun OS is not too rare...

Later,
Andrew Mullhaupt

karl@haddock.ima.isc.com (Karl Heuer) (03/05/90)

In article <762@hnm.Morgan.COM> amull@Morgan.COM (Andrew P. Mullhaupt) writes:
>In article <16048@haddock.ima.isc.com>, karl@haddock.ima.isc.com (Karl Heuer) writes:
>>But in that case he'd still get a warning `log10 used but not defined'
>
>No. This did not happen when I used lint on Sun OS 4.??.

You're right.  I'd forgotten how hard it is to get useful information out of
BSD lint; I try to do most of my linting on my SysV machine.  Okay, having
trapped myself in the corner, I will now proceed to walk across the wet paint.

I retract most of this thread.  My original comments stand, suitably modified:
(a) lint can help diagnose the problem (provided you tell it about the
library; this is `-lm' in most versions of Unix)
(b) if you don't have lint or equivalent functionality via compiler options,
then your vendor only sold you half a C compiler.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

wittig@gmdzi.UUCP (Georg Wittig) (03/05/90)

elzea@sersun0.essex.ac.uk (El-Zein A A) writes:
>	.
>	l = log10(8);

What about
	l = log10(8.0)		?
-- 
Georg Wittig   GMD-Z1.BI   P.O. Box 1240   D-5205 St. Augustin 1 (West Germany)
email: wittig@gmdzi.uucp   phone: (+49 2241) 14-2294
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
"Freedom's just another word for nothing left to lose" (Kris Kristofferson)