What is the origin of $number?
If it is read from a textual representation (STDIN, File), personally I would chose method 1. to scan for a dot followed by digits where at least one digit is not zero (something along $number =~ /\.0*[1-9]\d*/). Scanning for a dot allone is not sufficient.
If the origin of $number is a computation, than you have to take care of rounding issues when you apply method 2. Comparing $number with int($number) for equalness might fail due to rounding issues. So it might be more robust to do a comparison along abs($number - int($number)) < $epsilon (see Why do floating point numeric equality/inequality tests fail mysteriously?).
Update: Please note GrandFather's correct comment about the special case of the comparison $number == int($number). Indeed, abs($number - int($number)) itself may lead to false positives when $epsilon is ill chosen (see below).
for my $a (-2..10, 0.2, -0.2, 1 + 0.25e-15) { $_ = unpack("b*", pack("d", $a)); # double to bit-pattern s/(.{8})/$1 /g; tr[0][.]; # grouping&fmt. $_ = reverse $_; # formatting s/^(..)(.{12})(.*)/Sgn:$1 Exp: $2 Mant:(1,)$3/; print "$a\t -- $_\n"; }
-2 -- Sgn: 1 Exp: 1...... .... Mant: (1,).... ........ ........ ........ ........ ........ ........See the last line representing the smalles double greater than 1.0 ((1,)0000....00001)? (Not only) here, the given $epsilon-test would lead to a false positive if $epsilon was chosen too "big". In case int() is properly implemented (a valid assumption for modern CPUs and implementations, see IEEE_754), the integer part can be extracted without loss of precision from the float representation by shifting and masking the mantissa. For a real integer, this operation will lead to identical bit patterns that can be compared for equality.
-1 -- Sgn: 1 Exp: .111111 1111 Mant: (1,).... ........ ........ ........ ........ ........ ........
0 -- Sgn: . Exp: ....... .... Mant: (1,).... ........ ........ ........ ........ ........ ........
1 -- Sgn: . Exp: .111111 1111 Mant: (1,).... ........ ........ ........ ........ ........ ........
2 -- Sgn: . Exp: 1...... .... Mant: (1,).... ........ ........ ........ ........ ........ ........
3 -- Sgn: . Exp: 1...... .... Mant: (1,)1... ........ ........ ........ ........ ........ ........
4 -- Sgn: . Exp: 1...... ...1 Mant: (1,).... ........ ........ ........ ........ ........ ........
5 -- Sgn: . Exp: 1...... ...1 Mant: (1,).1.. ........ ........ ........ ........ ........ ........
6 -- Sgn: . Exp: 1...... ...1 Mant: (1,)1... ........ ........ ........ ........ ........ ........
7 -- Sgn: . Exp: 1...... ...1 Mant: (1,)11.. ........ ........ ........ ........ ........ ........
8 -- Sgn: . Exp: 1...... ..1. Mant: (1,).... ........ ........ ........ ........ ........ ........
9 -- Sgn: . Exp: 1...... ..1. Mant: (1,)..1. ........ ........ ........ ........ ........ ........
10 -- Sgn: . Exp: 1...... ..1. Mant: (1,).1.. ........ ........ ........ ........ ........ ........
0.2 -- Sgn: . Exp: .111111 11.. Mant: (1,)1..1 1..11..1 1..11..1 1..11..1 1..11..1 1..11..1 1..11.1.
-0.2 -- Sgn: 1 Exp: .111111 11.. Mant: (1,)1..1 1..11..1 1..11..1 1..11..1 1..11..1 1..11..1 1..11.1.
1 -- Sgn: . Exp: .111111 1111 Mant: (1,).... ........ ........ ........ ........ ........ .......1
OK, the comparison of $a and int($a) yields the correct result ($a is not an integer). But choosing the wrong $epsilon (e.g., here: 1e-15) would lead to a false positive - a typical characterstic when comparing against a limit - the limit controls the distribution of errors of first and second kind.my $a = 1+0.25e-15;# hidden bit and last bit of mantissa: 1 print "Test : is int.? correct?\n"; print "a != int(a) : no yes\n" if $a != int($a); $d = abs($a - int($a)); print "abs(a-int(a) < 1e-15: yes no!\n" if $d<1e-15; print "abs(a-int(a) < 1e-40: yes ???\n" if $d<1e-40; print "abs(a-int(a) > 0 : no yes\n" if $d>0; printf("epsilon < %g required (here!)\n", $d); __END__ Test : is int.? correct? a != int(a) : no yes abs(a-int(a) < 1e-15: yes no! abs(a-int(a) > 0 : no yes epsilon < 2.22045e-16 required (here!)
In reply to Re: How to determine whether a number has a decimal component?
by Perlbotics
in thread How to determine whether a number has a decimal component?
by Xenofur
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |