What is a concise way to test if floating point value is integral?

JS js.mdnq at gmail.com
Thu Aug 29 02:27:55 PDT 2013


On Thursday, 29 August 2013 at 08:58:02 UTC, Paul Jurczak wrote:
> On Thursday, 29 August 2013 at 08:26:11 UTC, Jonathan M Davis 
> wrote:
>> On Thursday, August 29, 2013 10:07:31 Paul Jurczak wrote:
>>> On Thursday, 29 August 2013 at 07:51:40 UTC, Jonathan M Davis
>>> wrote:
>>> [..]
>>> 
>>> > as any integral value in a float will fit in an
>>> > int.
>>> 
>>> [..]
>>> 
>>> Will it? Most of them will not fit
>>
>> Sure, they will. float has 32 bits, just like int, so it can't 
>> possibly hold a
>> value larger than an int can hold. This code passes with 
>> flying colors
>>
>>    foreach(i; int.min .. int.max)
>>        assert(cast(float)i == i);
>>
>>> but cast to int produces
>>> nonsensical value anyway as in this example:
>>> 
>>> cast(int)float.max
>>
>> So what? All you care about here is whether the value in the 
>> float is an
>> integral value. float.max isn't an integral value, so it 
>> really doesn't matter
>> if you get overflow when converting. It would have to convert 
>> back to the exact
>> same value when converting it back to a float, and it won't.
>>
>> assert(cast(int)float.max == float.max);
>>
>> will fail. It might make more sense to use to!int if you want 
>> to use the
>> resulting int for something, but all you're doing with it is 
>> comparing it
>> against the original float to see if it's the same value. If 
>> anything, the fact
>> that to!int throws would be a serious problem for what you're 
>> trying to do,
>> because if what you're testing for is whether a float holds an 
>> integral value,
>> throwing on overflow when converting to int would just get in 
>> your way. It
>> should just result in false in that case (because it's not an 
>> integral value,
>> or it wouldn't overflow), and the cast will result in false, 
>> unlike to!int.
>>
>> - Jonathan M Davis
>
> I should have used "integer" instead of "integral" to avoid 
> math vs. programming language confusion.
>
> Well, float.max is an integer number! Its value is 3.40282e+38. 
> The function I defined at the top of this page:
>
> bool isIntegral(T)(T x) {return x == round(x);}
>
> works correctly with float.max. Using cast(int) fails. I should 
> have written it as:
>
> bool isInteger(T)(T x) {return x == round(x);}

Yes, casting will not work because a float type can't be fully 
cast to an int without possible overflow.

Your method works fine. The only issue, the issue with comparing 
any floating point, is tolerance. How close to an int does a 
float have to be to be considered an int?

If you can afford to do something like `return (abs(x - round(x)) 
< tol)`.

(remember, numerical computations can result in floating point 
numbers that are suppose be integers but are not(accumulation of 
rounding errors). Using == results in using the tolerance of a 
float, its minimum value)



Also look at FXTRACT.


More information about the Digitalmars-d-learn mailing list