"John Matthews" <jm5...@...> wrote:
> praveen indian85 <praveen_indian85@> wrote:
> > dec=dec+temp*pow(2,i);
>
> pow() takes double arguments and returns a double.
> The following would be more appropriate:
>
> dec += temp * (1 << i);
>
> BTW is (int)pow(2, i) guaranteed to return the same
> as (1 << i) for say integer i=0..15 (assuming 32 bit
> int)?
Technically, you only need an int with at least 16 value
bits for (1 << i) to be well defined for i in [0..15].
But to answer your question, no, the standard doesn't
actually guarantee that. It says:
"The accuracy of the floating-point operations (+, -,
*, /) and of the library functions in <math.h> and
<complex.h> that return floating-point results is
implementation-defined, ..."
So it's a quality of implementation (QoI) issue. That said,
if you do find an implementation where the property doesn't
hold, you'll likely find that it's a contrived system, not
a serious product.
But as you've noticed, the two expressions are different
operations if i equals or exceeds the number of value bits.
The behaviour is undefined, but ordinary systems tend not
to trap, and instead produce deterministic values. Which
they are perfectly allowed to do.
However, unless a compiler can determine that i is indeed
within appropriate range, then it likely won't optimise
such a call to pow. Examine the following...
% type pow.c
#include <math.h>
#include <stdio.h>
int foo(int x) { return pow(2, x); }
int bar(int x) { return 1 << x; }
int main(void)
{
int i;
for (i = 0; i < 15; i++)
if (foo(i) != bar(i))
printf("fail: %d\n", i);
return 0;
}
% acc -S pow.c
% type pow.s
.file "pow.c"
.section .text
.p2align 4,,15
.globl _bar
_bar:
pushl %ebp
movl $1, %eax
movl %esp, %ebp
movl 8(%ebp), %ecx
popl %ebp
sall %cl, %eax
ret
.p2align 4,,15
.globl _foo
_foo:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
fildl 8(%ebp)
fstpl -8(%ebp)
movl -8(%ebp), %eax
movl -4(%ebp), %edx
pushl %edx
pushl %eax
pushl $1073741824
pushl $0
call _pow
fnstcw -18(%ebp)
movw -18(%ebp), %ax
fstpl -16(%ebp)
movb $12, %ah
movw %ax, -20(%ebp)
fldl -16(%ebp)
fldcw -20(%ebp)
fistpl -24(%ebp)
fldcw -18(%ebp)
movl -24(%ebp), %eax
leave
ret
.p2align 4,,15
.globl _main
_main:
leal 4(%esp), %ecx
andl $-16, %esp
xorl %eax, %eax
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.ident "GCC: (GNU) 4.3.2"
You'll notice that my implementation did not optimise
out the call to pow in foo().[1] However main() is
optimised effectively to a no-op since the compiler
was able to recognise that foo(i) will indeed equal
bar(i) for the iterated values of i!
[1] Since it has external linkage. See what happens
in gcc if you change it to static (internal linkage)
and turn up the optimisation level. :-)
--
Peter