## digitalmars.D.learn - What is a concise way to test if floating point value is integral?

• Paul Jurczak (6/6) Aug 28 2013 I'm writing this rather ugly:
• Paul Jurczak (5/11) Aug 28 2013 I defined a helper function:
• Jonathan M Davis (7/15) Aug 28 2013 There may be something in std.math which makes it cleaner, but I would h...
• Paul Jurczak (5/23) Aug 28 2013 Isn't type conversion:
• Jonathan M Davis (7/37) Aug 29 2013 Not really IMHO. std.conv.to does fancier conversions than casting does,...
• Paul Jurczak (8/10) Aug 29 2013 On Thursday, 29 August 2013 at 07:51:40 UTC, Jonathan M Davis
• Jonathan M Davis (19/33) Aug 29 2013 Sure, they will. float has 32 bits, just like int, so it can't possibly ...
• Paul Jurczak (10/56) Aug 29 2013 I should have used "integer" instead of "integral" to avoid math
• JS (13/76) Aug 29 2013 Yes, casting will not work because a float type can't be fully
• anonymous (9/27) Aug 29 2013 float can't hold more distinct values than int, but a float can
• Simen Kjaeraas (18/34) Aug 29 2013 First, that's showing the exact opposite of what you're saying it does.
"Paul Jurczak" <pauljurczak yahoo.com> writes:
```I'm writing this rather ugly:

sqrt(cast(float)D) != round(sqrt(cast(float)D)

line and I'm looking for more concise notation without
introducing a meaningless variable to hold expression being
tested. Is there an equivalent of std.math.trunc(), which would
return fractional portion instead, maybe frac()?
```
Aug 28 2013
"Paul Jurczak" <pauljurczak yahoo.com> writes:
```On Thursday, 29 August 2013 at 05:47:43 UTC, Paul Jurczak wrote:
I'm writing this rather ugly:

sqrt(cast(float)D) != round(sqrt(cast(float)D)

line and I'm looking for more concise notation without
introducing a meaningless variable to hold expression being
tested. Is there an equivalent of std.math.trunc(), which would
return fractional portion instead, maybe frac()?

I defined a helper function:

bool isIntegral(T)(T x) {return x == round(x);}

but is there something in D libraries to give me this
functionality?
```
Aug 28 2013
Jonathan M Davis <jmdavisProg gmx.com> writes:
```On Thursday, August 29, 2013 07:47:16 Paul Jurczak wrote:
I'm writing this rather ugly:

sqrt(cast(float)D) != round(sqrt(cast(float)D)

line and I'm looking for more concise notation without
introducing a meaningless variable to hold expression being
tested. Is there an equivalent of std.math.trunc(), which would
return fractional portion instead, maybe frac()?

There may be something in std.math which makes it cleaner, but I would have
thought that the to test whether a floating point value is an integral value,
you'd just cast it to an integral type and then compare that against the
original. e.g.

auto isIntegral = cast(int)my_float == my_float;

- Jonathan M Davis
```
Aug 28 2013
"Paul Jurczak" <pauljurczak yahoo.com> writes:
```On Thursday, 29 August 2013 at 06:23:18 UTC, Jonathan M Davis
wrote:
On Thursday, August 29, 2013 07:47:16 Paul Jurczak wrote:
I'm writing this rather ugly:

sqrt(cast(float)D) != round(sqrt(cast(float)D)

line and I'm looking for more concise notation without
introducing a meaningless variable to hold expression being
tested. Is there an equivalent of std.math.trunc(), which would
return fractional portion instead, maybe frac()?

There may be something in std.math which makes it cleaner, but
I would have
thought that the to test whether a floating point value is an
integral value,
you'd just cast it to an integral type and then compare that
against the
original. e.g.

auto isIntegral = cast(int)my_float == my_float;

- Jonathan M Davis

Isn't type conversion:

auto isIntegral = to!int(my_float) == my_float;

more recommended/idiomatic D way to deal with built-in types?
```
Aug 28 2013
Jonathan M Davis <jmdavisProg gmx.com> writes:
```On Thursday, August 29, 2013 08:50:47 Paul Jurczak wrote:
On Thursday, 29 August 2013 at 06:23:18 UTC, Jonathan M Davis

wrote:
On Thursday, August 29, 2013 07:47:16 Paul Jurczak wrote:
I'm writing this rather ugly:

sqrt(cast(float)D) != round(sqrt(cast(float)D)

line and I'm looking for more concise notation without
introducing a meaningless variable to hold expression being
tested. Is there an equivalent of std.math.trunc(), which would
return fractional portion instead, maybe frac()?

There may be something in std.math which makes it cleaner, but
I would have
thought that the to test whether a floating point value is an
integral value,
you'd just cast it to an integral type and then compare that
against the
original. e.g.

auto isIntegral = cast(int)my_float == my_float;

- Jonathan M Davis

Isn't type conversion:

auto isIntegral = to!int(my_float) == my_float;

more recommended/idiomatic D way to deal with built-in types?

Not really IMHO. std.conv.to does fancier conversions than casting does, and
it throws in cases of overflow, neither of which are of any benefit when
converting a float to an int, as any integral value in a float will fit in an
int. Using to would just create extra overhead for no extra benefit in this
case.

- Jonathan M Davis
```
Aug 29 2013
"Paul Jurczak" <pauljurczak yahoo.com> writes:
```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, but cast to int produces
nonsensical value anyway as in this example:

cast(int)float.max

With to!int you get a proper warning.
```
Aug 29 2013
Jonathan M Davis <jmdavisProg gmx.com> writes:
```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
```
Aug 29 2013
"Paul Jurczak" <pauljurczak yahoo.com> writes:
```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);}
```
Aug 29 2013
"JS" <js.mdnq gmail.com> writes:
```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.
```
Aug 29 2013
"anonymous" <anonymous example.com> writes:
```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.

float can't hold more distinct values than int, but a float can
have integer values greater than int.max. (Also, there are int
values that a float cannot store.)

This code passes with flying colors

foreach(i; int.min .. int.max)
assert(cast(float)i == i);

That's because both sides are casted to float.

[...]
float.max isn't an integral value,

It's not a value that an int can store, but it's an integer in
the mathematical sense.
```
Aug 29 2013
"Simen Kjaeraas" <simen.kjaras gmail.com> writes:
```On 2013-08-29, 10:25, 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);

First, that's showing the exact opposite of what you're saying it does.
Second, it doesn't even show that.

Your code is equivalent to:

foreach(i; int.min .. int.max)
assert(cast(float)i == cast(float)i);

If that does not pass with flying colors, I'd be surprised. Now try this:

foreach(i; int.min .. int.max) {
float f = i; // DMD optimizes out cast(int)cast(float)int
assert(cast(int)f == i);
}

It will fail for odd numbers in the range 16,777,216-33,554,432, and for
numbers not divisible by 4 in the range to the next power of two, then 8,
and so on. These numbers are simply not representable by a float.

For more information:
http://floating-point-gui.de/formats/fp/

--
Simen
```
Aug 29 2013