lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Shmuel Zeigerman <shmuz@bezeqint.net> writes:

> David Kastrup wrote:
>> That's all pretty useless since there is no standard behavior for
>> (int)x, and besides, (int)x may overflow.
>>
>> If we disregard overflow, of course it is easiest to just do
>>
>> double floor(double x)
>> {
>>   double y = (double)(int)x;
>>   return y > x ? y-1.0 : x;
>> }
>
> You're right with regards to overflow. Your version of floor is
> however buggy.

How so?  Can you give an example where it would fail?  The only
assumptions my version makes is that (double)(int)x is integral and that
abs(x-(int)x) < 1.0 which is rather reasonable.

So after the first assignment, we have

abs(x-y)<1.0 and y=integral;

So if y>x, we have x+1 > y > x and return integral y-1 with x > y-1 > x-1.
And if not, we have x >= y > x-1 and return integral y with x >= y > x-1.

So we return an integral z with x >= z > z-1.  Which is what floor is
all about.  The only source of problem is overflow/rounding.  And then
the only case that really poses an _additional_ problem is where y-1.0
happens to be y.  That can (without integer overflow) only happen when
y-1.0 is not representable, namely when floating precision is less than
integer precision.  But then floor(x) will return a _wrong_ value
anyway.  It's just that a wrong value that is smaller will probably be
nicer than a wrong value that is larger.

> Here is a shortened version:
>
> double floor(double x)
> {
>   double y = (double)(int)x;
>   return (x >= 0 || x == y) ? y : y-1;
> }

No, that is not "shortened".  It is something completely different and
has a lot more assumptions about how conversion works.  And even using
all those assumptions, it does not get more cases right than my version.

-- 
David Kastrup