views:

351

answers:

5

I have a double which is:

double mydouble = 10;

and I want 10^12, so 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10. I tried

double newDouble = pow(10, 12);

and it returns me in NSLog: pow=-1.991886

makes not much sense... I think pow isn't my friend right?

+6  A: 

try pow(10.0, 12.0). Better yet, #include math.h.

To clarify: If you don't include math.h, the compiler assumes that pow() returns an integer. Including math.h brings in a prototype like

double pow(double, double);

So the compiler can understand how to treat the arguments and the return value.

Richard Pennington
What would be the reason behind this? Is there another `pow` defined with Obj-C which does something entirely unrelated? That would strike me as incredibly stupid, actually.
Joey
The reason is that without including <math.h>, pow() has not been declared at all. This is legal in C (not in C++), and the compiler assumes that pow() accepts int arguments and returns an int, and generates its code accordingly. Most people turn on the appropriate compiler options to either warn or error on undeclared functions.
Rudedog
A: 

That's the right syntax for pow, what format string are you passing to NSLog(…)?

Ben Gottlieb
A: 

did you try casting to a double:

NSLog(@"(double)pow(10, 12)                    = %lf", (double)pow(10, 12));
ennuikiller
`pow` already returns a double, so that cast will probably just be ignored by the compiler.
Joey
This cast doesn't do what you expect. Need to include math.h.
Richard Pennington
+4  A: 

I couldn't even get the program to compile without:

#include <math.h>

When using math functions like this you should ALWAYS include math.h and make sure you are calling the right pow function. Who knows what the other pow function might be ... it could stand for "power wheels" haha

Brian T Hannan
Actually, <cmath> rather than <math.h>, as he is asking about C++.
ChrisInEdmonton
also need to link using -lm
Neeraj
@Chris: he's asking about Objective-C, not C++. @Neeraj: `-lm` is implicit with the Apple compiler tools.
Stephen Canon
Ah. Yesterday, it said C++, today Objective-C and C. sigh.
ChrisInEdmonton
+4  A: 

Here's how to compute x^12 with the fewest number of multiplications.

y = x*x*x; y *= y; y *= y;

The method comes from Knuth's Seminumerical Algorithms, section 4.6.3.

John D. Cook
Note that while this will generally be faster than `pow(x,12.0)`, it will also be less accurate on platforms that have a high-quality math library. This may or may not matter, depending on how the result is to be used.
Stephen Canon
I doubt that it would be less accurate.
Nosredna
For the specific value of 10.0, the repeated multiplication method will be at least as accurate. However, a *good* library implementation of `pow(x, 12.0)` will deliver a result with less that 1 ulp of error for all double-precision values of `x`, whereas repeated multiplication can have a rather larger error (2 or 3 ulps would be reasonably common).
Stephen Canon
Are the standard supplied libraries in today's commonly-used compilers "good" or "high-quality?" A multiplication is supposed to be within half a ulp, right, and there are four multiplications here. Good libraries do get pow within 1 ulp, I believe, but there are a lot of bad libraries out there, and some of them shuffle pow off to exp. So it certainly depends on the library. I'd trust a library to screw up less on multiplication than on pow. I find it odd that the OP gave us small integers as inputs. Not sure if that's going to be common for him or not.
Nosredna
Certainly Intel's and Apple's libraries (the two with which I am familiar) deliver results more accurate than 1 ulp. I don't know what the state of numerics in glibc and the MS library is, but I believe that HP and Sun both deliver sub-ulp accurate answers.
Stephen Canon
This shouldn't depend on libraries but on hardware. Intel has had accurate implementations of pow() baked into the chip microcode since at least as far back as the 486. (I worked on such microcode.) I imagine other chips do too. As long as the numerical library calls native instructions, accuracy shouldn't be an issue. (Java libraries, however, do not call native instructions for transcendental functions. The concern here is lost efficiency rather than lost accuracy.)
John D. Cook
Does the ARM have that?
Nosredna
@John: It depends entirely on libraries. While there are indeed x87 instructions for transcendental functions, modern math libraries use them sparingly (if at all), because it is typically faster to do the computations in software on SSE. @Nosredna: ARM does not have transcendental function instructions.
Stephen Canon
Then I would not be surprised if the 4 multiplies are more accurate on the ARM than the pow().
Nosredna
Depends on what math library you're using on the ARM. A vendor could build crlibm for ARM, for example, and get a correctly rounded pow (< 0.5 ulp of error, obviously more accurate than four multiplies). Or they could implement the same software implementation that they use on other platforms and deliver a result with < 1ulp of error. Or they could roll their own implementation targeted at that platform, meeting the same accuracy bound. I believe that each of these approaches have been used by at least one vendor.
Stephen Canon
Of course, you might have a lazy system library implementor, and the accuracy of pow could be terrible. I know of at least one vendor who uses this approach, too =)
Stephen Canon