Perl-Sensitive Sunglasses PerlMonks

### modulus and floating point numbers

by dextius (Monk)
 on Nov 18, 2008 at 02:22 UTC Need Help??

dextius has asked for the wisdom of the Perl Monks concerning the following question:

Simple question. I need a simple way of detecting values that are "sub penny".. Is there a better way to do it than this? (I believe the code is correct, but I'm hoping there may be a faster implementation)
```sub is_subpenny
{
my \$number = \$_[0];

return ((\$number*100) - int(\$number*100) > 0);
}

Replies are listed 'Best First'.
Re: modulus and floating point numbers
by GrandFather (Saint) on Nov 18, 2008 at 02:34 UTC
```sub is_subpenny {
my \$number = abs (\$_[0] * 100);

return \$number - int (\$number) > 0;
}

is faster by avoiding an extra multiply and also works for negative numbers although the abs may slow it down again.

Perl reduces RSI - it saves typing
Re: modulus and floating point numbers
by BrowserUk (Patriarch) on Nov 18, 2008 at 02:57 UTC

Whether it's faster or not you'll have to determine yourself, but it's another way:

```use POSIX qw[ fmod ];;
print fmod( \$_, 100 ) for 12300, 12301, 12399;;
0
1
99

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

I'm not sure if I understand the question, but:

```[0] Perl> print fmod( \$_, 100 ) for 12300, 12301, 12399, .00001;;
0
1
99
1e-005

Or do you mean this:

```[0] Perl> print fmod( \$_, 1 ) for map{ (\$_, -\$_ ) } 12300, 12301, 1239
+9, .00001;;
0
0
0
0
0
0
1e-005
-1e-005

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
Re: modulus and floating point numbers
by ccn (Vicar) on Nov 18, 2008 at 03:17 UTC
```#!/usr/bin/perl

use strict;
use warnings;
use Benchmark qw(cmpthese);

my @a = map { (rand() * 1000) / 1000 } 1 .. 1000;

cmpthese(-1, {
'GF'  => sub {GF(\$_)  for @a},
'GF2' => sub {GF2(\$_) for @a},
'dex' => sub {dex(\$_) for @a},
'ccn' => sub {ccn(\$_) for @a}});

sub GF {
my \$number = abs(\$_[0] * 100);
return \$number - int (\$number) > 0;
}

sub GF2 {
my \$number = \$_[0] * 100;
return \$number - int (\$number) > 0;
}

sub ccn {
\$_[0] =~ /\..../;
}

sub dex {
my \$number = \$_[0];
return ((\$number*100) - int(\$number*100) > 0);
}

__END__

Rate  dex   GF  GF2  ccn
dex  931/s   --  -7% -19% -28%
GF  1000/s   7%   -- -13% -23%
GF2 1152/s  24%  15%   -- -11%
ccn 1297/s  39%  30%  13%   --
You took off the addition and the parens.. I got..
```      Rate  ccn  dex   GF  GF2
ccn  296/s   -- -73% -74% -76%
dex 1097/s 270%   --  -2% -10%
GF  1124/s 279%   2%   --  -7%
GF2 1213/s 309%  11%   8%   --
I took off addition wittingly. One can skip addition if input data is numeric. Situation becomes worse if input must be validated.

And once again, I am not shure if we can rely on the third digit after a floating point. Indeed, I will never use that sub.

Re: modulus and floating point numbers
by ccn (Vicar) on Nov 18, 2008 at 02:45 UTC
I am not sure, but what about?
```sub is_subpenny {
(\$_[0]+0) =~ /\..../;
}

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://724170]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?