The stupid question is the question not asked PerlMonks

### Some simple math and absolute values

by sidmuchrock (Novice)
 on May 23, 2020 at 01:55 UTC Need Help??

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

I'm wondering how to do this better than my 4 line method. Feels like I'm missing something obvious. But example code below works Basically I want to show weight * price = total but allow a minimum weight but if it's a negative weight it should be the reverse of the above Expected results: 2.3 = \$23 .3 = \$10 0 = \$10 -.3 = -\$10 -2.3 = -\$23
```\$wt = \$ARGV[0];

\$min = 1;
\$price = 10;

while (\$wt ne '') {
\$nwt = abs(\$wt);
\$nwt = \$min if \$nwt<\$min;
\$total = \$nwt*\$price;
\$total = -\$total if \$wt<0;

print "Price: \$total\n";

print "Next Weight: ";
chomp(\$wt = <stdin>);
}

Replies are listed 'Best First'.
Re: Some simple math and absolute values (updated)
by haukex (Chancellor) on May 23, 2020 at 07:56 UTC

TIMTOWTDI...

```use warnings;
use strict;

our \$MIN = 1;
our \$PFACT = 10;
sub price {
my \$weight = shift;
return abs \$weight < \$MIN
? ( \$weight < 0 ? -\$PFACT : \$PFACT ) : \$PFACT * \$weight;
}

use Test::More;
is price(\$\$_[0]), \$\$_[1] for
[ 5.0, 50],[ 2.3, 23],[ 1.1, 11],[ 1, 10],[ 0.3, 10],[0,10],
[-5.0,-50],[-2.3,-23],[-1.1,-11],[-1,-10],[-0.3,-10];
{    local \$MIN = 3;
is price(\$\$_[0]), \$\$_[1] for
[ 5.0, 50],[ 2.3, 10],[ 1.1, 10],[ 1, 10],[ 0.3, 10],[0,10],
[-5.0,-50],[-2.3,-10],[-1.1,-10],[-1,-10],[-0.3,-10];  }
{    local \$PFACT = 5;
is price(\$\$_[0]), \$\$_[1] for
[ 5.0, 25],[ 2.3, 11.5],[ 1.1, 5.5],[ 1, 5],[ 0.3, 5],[0,5],
[-5.0,-25],[-2.3,-11.5],[-1.1,-5.5],[-1,-5],[-0.3,-5];  }
{    local (\$MIN,\$PFACT) = (3,5);
is price(\$\$_[0]), \$\$_[1] for
[ 5.0, 25],[ 2.3, 5],[ 1.1, 5],[ 1, 5],[ 0.3, 5],[0,5],
[-5.0,-25],[-2.3,-5],[-1.1,-5],[-1,-5],[-0.3,-5];  }
done_testing;

Update: Expanded test cases. Please check if this is what you want, keeping in mind the caveat that jo37 mentioned!

Which can be "golfed" to
```    \$PFACT * (\$weight, (\$weight >= 0) * 2 - 1)[abs \$weight < \$MIN]

map{substr\$_->[0],\$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Some simple math and absolute values
by jo37 (Monk) on May 23, 2020 at 12:03 UTC

The values in the given example have one small flaw:
As \$min is one, some code would pass a test even if it didn't calculate \$min * \$price but used \$price instead.

Greetings,
-jo

\$gryYup\$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p\$
Re: Some simple math and absolute values
by parv (Vicar) on May 23, 2020 at 06:48 UTC

Could reduce to 2 statements, does not seem any better ...

```    \$nwt = abs( \$wt );
\$total = ( \$nwt < \$min ? \$min : \$nwt )
* \$price
* ( \$wt < 0 ? -1 : 1 )
;
Re: Some simple math and absolute values
by BillKSmith (Prior) on May 23, 2020 at 23:37 UTC
The following code may not be any shorter than yours, but I find it much easier to understand. The tests demonstrate that it produces the same total as yours for a variety of weights.
```use strict;
use warnings;
use Test::More tests => 11;

my \$min   =  1;
my \$price = 10;

sub total {
my \$wt = \$_[0];
my \$Total
= (\$wt < -\$min) ?  \$price * \$wt
: (\$wt < 0    ) ?  \$price * (-\$min)
: (\$wt < \$min ) ?  \$price * \$min
:                  \$price * \$wt
;
return \$Total;
}

sub refrence {
my \$wt = \$_[0];
my \$nwt = abs(\$wt);
\$nwt = \$min if \$nwt<\$min;
my \$total = \$nwt*\$price;
\$total = -\$total if \$wt<0;
return \$total;
}

for (0..10) {
my \$trial_wt = .3 * (\$_ -5);
is( total(\$trial_wt), refrence(\$trial_wt), "Weight: \$trial_wt");
}

OUTPUT:

```1..11
ok 1 - Weight: -1.5
ok 2 - Weight: -1.2
ok 3 - Weight: -0.9
ok 4 - Weight: -0.6
ok 5 - Weight: -0.3
ok 6 - Weight: 0
ok 7 - Weight: 0.3
ok 8 - Weight: 0.6
ok 9 - Weight: 0.9
ok 10 - Weight: 1.2
ok 11 - Weight: 1.5
Bill
Re: Some simple math and absolute values
by syphilis (Bishop) on May 23, 2020 at 02:19 UTC
Hi,

I think this will do the same:
Update: No, it fails to do the right thing for negative \$wt values greater than -1.
```\$wt = \$ARGV[0];

\$min = 1;
\$price = 10;

while (\$wt ne '') {
\$wt = \$min if abs(\$wt)< \$min;
print "Price: " \$wt * \$price, "\n";

print "Next Weight: ";
chomp(\$wt = <stdin>);
}
Cheers,
Rob
Re: Some simple math and absolute values
by 1nickt (Abbot) on May 23, 2020 at 03:20 UTC

Hi,

I am not a math expert nor an algorithm expert nor a golfer, Perl or otherwise, but maybe something like this?

```my \$price = (\$wt || 1) * 10;
\$price = 10 * \$price/abs(\$price) if abs(\$price) < 10;

Output:

```perl blrg.pl 2.3

Price: 23
Next Weight: .3
Price: 10
Next Weight: 0
Price: 10
Next Weight: -.3
Price: -10
Next Weight: -2.3
Price: -23
Next Weight:

Hope this helps!

The way forward always starts with a minimal test.
This was what I was missing last night! I kept trying to say if \$wt/abs(\$wt) and it was dying in the 0 case, but by turning the 0 to \$min in the possible total and then checking \$total/abs(\$total) that solved. it. Thank you.
```        \$total = (\$wt || \$min) * \$price;
\$total = \$total/abs(\$total) * \$price * \$min if abs(\$wt) < \$min
+;

Create A New User
Node Status?
node history
Node Type: perlquestion [id://11117138]
Approved by 1nickt
Front-paged by 1nickt
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2020-06-05 11:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Do you really want to know if there is extraterrestrial life?

Results (37 votes). Check out past polls.

Notices?