views:

120

answers:

3

Hi,

I am coding up an implementation of Interpolation Search in C.

The question is actually rather simple, I need to use the floating operations to do linear interpolation to find the correct index which will eventually be an integer result.

In particular my probe index is:

t = i + floor((((k-low)/(high-low)) * (j-i)));

where, i,j,k,t are unsigned ints, and high,low are doubles.

Would this be equivalent to:

t = i + (unsigned int)(((k-low)/(high-low)) * (j-i));

Is there any reason I would actually want to use math.h floor* functions over just a simple (int) typecast?

+1  A: 

They are equivalent only for positive numbers. From the C99 specification (§6.3.1.4/1):

When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.

So, for positive numbers, the result of casting a floating-point value to an integral type is equivalent to calling floor, but for negative number is is equivalent to calling ceil.

James McNellis
I see, thanks for the detailed information. The good news is: ((k-low)/(high-low)) * (j-i) is guaranteed to be >=0 if the algorithm is coded correctly (since it's an index into an array afterall).So this appears to be a suitable option.Thanks.
nobody
@nobody: Note that from a performance standpoint, casting to an integral type might not be faster than using `floor`. Casting to an integral type probably requires a write to memory (on the x86, it's all but guaranteed), while calling `floor` may not, since its result is a floating point value. Your mileage may vary, but watch out for premature and/or misguided optimization.
James McNellis
+1  A: 

They are different when the value is < 0.

floor(-1.5) = -2.0
(int)-1.5 = 1
R Samuel Klatchko
A: 

In your case, they are equivalent. But for negative numbers,

g++> printf("%g %d %u\n", floor(-5.5), (int)(-5.5), (unsigned)(-5.5));
-6 -5 0

(actually, casting a negative real number ≤ -1 to unsigned integer is implementation-defined (or undefined behavior?).)

Also, floor returns a double, so i + floor(...) will be performed as a floating point operation instead of an integer operation.

KennyTM
Casting a negative real value to an unsigned integral type is undefined: "If the value of the integral part cannot be represented by the integer type, the behavior is undefined" (§6.3.1.4/1). This is somewhat interesting, since casting a negative integral value to an unsigned integral type _is_ well-defined: "if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type" (§6.3.1.3/2). (citations from C99 spec).
James McNellis
@James: Footnote (50) writes *"The remaindering operation performed when a value of integer type is converted to unsigned type need not be performed when a value of real floating type is converted to unsigned type."* which seems to suggest the expected conversion is `real -> signed -> unsigned`, makes me unsure whether it should be undefined (as in 6.3.1.4) or implementation-defined (6.3.1.3).
KennyTM