Round float to integer if whole number

Hi,

I’m looking for a way to pick out the whole numbers (ff) in the function
below:

x = 17
w = 4.000

while x > 0

ff = x / w

if ff > 0 and ff.is_a? wholenumber
     puts " #{ff} is a whole number"
end

x -= 1

end

Thanx

Liquid

Possible tests:
ff.floor == ff
ff % 1 == 0

If x is always an integer i would use the mod operator ( x % w == 0
==> x/w integer)

2011/12/14 Ronnie Aa [email protected]:

Gunther D. wrote in post #1036785:

Possible tests:
ff.floor == ff
ff % 1 == 0

If x is always an integer i would use the mod operator ( x % w == 0
==> x/w integer)

2011/12/14 Ronnie Aa [email protected]:

thanxs Gunther!

On Wed, Dec 14, 2011 at 11:21 PM, Ronnie Aa [email protected] wrote:

thanxs Gunther!
That test does not work reliably:

irb(main):006:0> x = 1.0
=> 1.0
irb(main):007:0> x.class
=> Float
irb(main):008:0> 20.times do |i|
irb(main):009:1* y = x + (10.0 ** -i)
irb(main):010:1> printf “%4d %20.16f %s\n”, i, y, y == y.floor
irb(main):011:1> end
0 2.0000000000000000 true
1 1.1000000000000001 false
2 1.0100000000000000 false
3 1.0009999999999999 false
4 1.0001000000000000 false
5 1.0000100000000001 false
6 1.0000009999999999 false
7 1.0000001000000001 false
8 1.0000000099999999 false
9 1.0000000010000001 false
10 1.0000000001000000 false
11 1.0000000000100000 false
12 1.0000000000010001 false
13 1.0000000000000999 false
14 1.0000000000000100 false
15 1.0000000000000011 false
16 1.0000000000000000 true
17 1.0000000000000000 true
18 1.0000000000000000 true
19 1.0000000000000000 true
=> 20

irb(main):024:0* x = BigDecimal.new “1.0”
=> #BigDecimal:102e06c0,‘0.1E1’,9(18)
irb(main):025:0> 20.times do |i|
irb(main):026:1* y = x + (BigDecimal.new(“10.0”) ** -i)
irb(main):027:1> printf “%4d %30.24f %s\n”, i, y, y == y.floor
irb(main):028:1> end
0 2.000000000000000000000000 true
1 1.100000000000000088817842 false
2 1.010000000000000008881784 false
3 1.000999999999999889865876 false
4 1.000099999999999988986588 false
5 1.000010000000000065512040 false
6 1.000000999999999917733362 false
7 1.000000100000000058386718 false
8 1.000000009999999939225290 false
9 1.000000001000000082740371 false
10 1.000000000100000008274037 false
11 1.000000000010000000827404 false
12 1.000000000001000088900582 false
13 1.000000000000099920072216 false
14 1.000000000000009992007222 false
15 1.000000000000001110223025 false
16 1.000000000000000000000000 false
17 1.000000000000000000000000 false
18 1.000000000000000000000000 false
19 1.000000000000000000000000 false
=> 20

It is better to define “equality” differently for floating point
numbers. There are a few common approaches:

  1. Define a maximum difference that you accept, e.g.

irb(main):029:0> x = 1.0
=> 1.0
irb(main):030:0> 20.times do |i|
irb(main):031:1* y = x + (10.0 ** -i)
irb(main):032:1> printf “%4d %30.24f %s\n”, i, y, (y - y.floor).abs <
1e-5
irb(main):033:1> end
0 2.000000000000000000000000 true
1 1.100000000000000088817842 false
2 1.010000000000000008881784 false
3 1.000999999999999889865876 false
4 1.000099999999999988986588 false
5 1.000010000000000065512040 false
6 1.000000999999999917733362 true
7 1.000000100000000058386718 true
8 1.000000009999999939225290 true
9 1.000000001000000082740371 true
10 1.000000000100000008274037 true
11 1.000000000010000000827404 true
12 1.000000000001000088900582 true
13 1.000000000000099920072216 true
14 1.000000000000009992007222 true
15 1.000000000000001110223025 true
16 1.000000000000000000000000 true
17 1.000000000000000000000000 true
18 1.000000000000000000000000 true
19 1.000000000000000000000000 true
=> 20

  1. Define a maximum delta for the factor to 1

irb(main):034:0> 20.times do |i|
irb(main):035:1* y = x + (10.0 ** -i)
irb(main):036:1> printf “%4d %30.24f %s\n”, i, y, ((y / y.floor) -
1).abs < 1e-5
irb(main):037:1> end
0 2.000000000000000000000000 true
1 1.100000000000000088817842 false
2 1.010000000000000008881784 false
3 1.000999999999999889865876 false
4 1.000099999999999988986588 false
5 1.000010000000000065512040 false
6 1.000000999999999917733362 true
7 1.000000100000000058386718 true
8 1.000000009999999939225290 true
9 1.000000001000000082740371 true
10 1.000000000100000008274037 true
11 1.000000000010000000827404 true
12 1.000000000001000088900582 true
13 1.000000000000099920072216 true
14 1.000000000000009992007222 true
15 1.000000000000001110223025 true
16 1.000000000000000000000000 true
17 1.000000000000000000000000 true
18 1.000000000000000000000000 true
19 1.000000000000000000000000 true
=> 20

Kind regards

robert

That test does not work reliably:
You’re right, but floating point numbers don’t work reliably (as one
can see in your examples, one has always conversion and rounding
errors)

Nonetheless if one has to work with floating point numbers it is surly
better to define equality in terms of some delta error tolerance.

Converting to a string was also one of my ideas. Although it was not
completely clear to me how to achieve that.

So thanx for your input…

Only drawback of this method is it’s lack of elegance I think…

On Fri, Dec 16, 2011 at 7:48 PM, Ronnie Aa [email protected] wrote:

Converting to a string was also one of my ideas. Although it was not
completely clear to me how to achieve that.

So thanx for your input…

Only drawback of this method is it’s lack of elegance I think…

Yeah. I’d go with a proximity check like

def whole? x
(x - x.floor) < 1e-6
end

Kind regards

robert

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 12/15/2011 05:21 AM, Gunther D. wrote:

That test does not work reliably:
You’re right, but floating point numbers don’t work reliably (as
one can see in your examples, one has always conversion and
rounding errors)

Nonetheless if one has to work with floating point numbers it is
surly better to define equality in terms of some delta error
tolerance.

I would think the most accurate way to do it would be to convert the
number to a string, split on the ‘.’ and then check if a number
besides ‘0’ is in the second part of the list. For example

irb(main):001:0> whole, nonwhole = 2.0 , 2.333
=> [2.0, 2.333]
irb(main):002:0> puts whole.class()
Float
=> nil
irb(main):003:0> puts nonwhole.class()
Float
=> nil
irb(main):004:0> whole_split = whole.to_s.split(‘.’)[1]
=> “0”
irb(main):005:0> nonwhole_split = nonwhole.to_s.split(‘.’)[1]
=> “333”
irb(main):006:0> /[1-9]/.match(whole_split)
=> nil
irb(main):007:0> /[1-9]/.match(nonwhole_split)
=> #<MatchData “3”>


frosty
public key: unluckyfrosty.net/public_key
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)

iQEcBAEBAgAGBQJO6n9WAAoJEMWQxuocG7AklLsH/AtnrXbWH29Hr+FrZwp0/LWt
R41fQ9sAezWmYLdERdh/07jzv0ZEOlTjUg+yZ/HRBeA5xvxeIwMS0HNANvnUDeKt
YcPFggAF0oG6z1/a9LAJpRJUlidnxFfQRrScRd/v5T6ojuSewFcKFjJW3Tkps85v
1NhZUQRuIJTO+UIoCmsp3ErHsDzs6wgSbSw6eJ0DjkCJdzqnSMLsUohqN0B1MuuR
nhulfXfOmpGza9JbqAbMfNc9JaIaxn2HAMZA2Iag0R8yC4S/BTvNOtNasVHeFYxD
AjteZtxkXZRjV0iKY5tKQHe1Jb1PqCuLTUPz97x+SBsmD3ILUwsfLU3SZ0x3+tI=
=i6EY
-----END PGP SIGNATURE-----

Converting to a string isn’t better as directly comparing the numbers,
it just adds more complexity to the code.

2011/12/16 Ronnie Aa [email protected]: