Just another Perl shrine PerlMonks

### Decimals to fractions

by oko1 (Deacon)
 on Jul 16, 2012 at 12:43 UTC ( #982023=CUFP: print w/replies, xml ) Need Help??

I'd imagine there's a module out there to do this, but I just threw this together in a couple of minutes. Besides, it was fun. :)

There are lots of times that I need to figure out this kind of stuff - I live on a boat and ride a motorcycle, so I'm always wrenching on something. In fact, I did something like this many, many years ago, but somehow managed to lose track of it... actually, I recall that implementation being quite a naive one (I was just starting to learn programming then.) Hope it's of use to others as well!

```#!/usr/bin/perl
# By: Ben Okopnik <ben@okopnik.com>, 07:45 2012-07-16
# Finds nearest "tape measure" fraction for a given decimal
use warnings;
use strict;

die "Usage: ", \$0 =~ /([^\/]+)\$/, " <number> [tolerance]\n"
unless @ARGV && \$ARGV[0] =~ /^(\d+)?(\.\d+)\$/;  # Yep, positives o
+nly :)
my \$int = \$1 || 0;
my \$dec = \$2;
die "No mantissa\n" unless \$dec > 0;
die "Not a reasonable tolerance\n"
if \$ARGV[1] && \$ARGV[1] !~ /^0?\.\d+\$/;

my \$tolerance = \$ARGV[1] || .001;        # 1 mil is the default
my \$denom = 2;
{
for my \$num (1 .. \$denom - 1){
die \$int + \$dec, " is equal to \$int \$num/\$denom (+/-\$tolerance
+)\n"
if abs(\$dec - \$num / \$denom) <= \$tolerance;
}
\$denom *= 2;
redo;
}
```--
I hate storms, but calms undermine my spirits.
-- Bernard Moitessier, "The Long Way"```

Replies are listed 'Best First'.
Re: Decimals to fractions
by tobyink (Abbot) on Jul 16, 2012 at 15:04 UTC

This one has no tolerance - it should always be exact (except in the case of overflowing the bounds of integer arithmetic for your architecture).

```use 5.010;

say fraction_for_decimal(\$_)
for qw( 0.3456 1.251 -0.1 -0.25 );

sub fraction_for_decimal
{
my \$decimal = shift;
my \$mult    = 10 ** length [ split m{[.]}, \$decimal ]->[1];
my (\$num, \$den) = (int(\$decimal * \$mult), \$mult);
my \$hcf = _hcf(\$num, \$den);
\$_ /= \$hcf for (\$num, \$den);
return "\$num/\$den";
}

# Stolen from Number::Fraction.
sub _hcf {
my (\$x, \$y) = @_;
(\$x, \$y) = (\$y, \$x) if \$y > \$x;
return \$x if \$x == \$y;
while (\$y) {
(\$x, \$y) = (\$y, \$x % \$y);
}
return abs(\$x);  # changed this
}

__END__
216/625
1251/1000
-1/10
-1/4
perl -E'sub Monkey::do{say\$_,for@_,do{(\$monkey=[caller(0)]->[3])=~s{::}{ }and\$monkey}}"Monkey say"->Monkey::do'
Re: Decimals to fractions
by Athanasius (Chancellor) on Jul 16, 2012 at 14:43 UTC
I'd imagine there's a module out there...

For the record, there’s a core module Math::BigRat which handles rational numbers of arbitrary size, and converts to and from floats, etc. See:

Athanasius <°(((><contra mundum

[doc://Math::BigRat] => Math::BigRat

[mod://Math::BigRat] => Math::BigRat

I reckon we are the only monastery ever to have a dungeon stuffed with 16,000 zombies.

Create A New User
Node Status?
node history
Node Type: CUFP [id://982023]
Front-paged by Arunbear
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2018-06-18 11:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Should cpanminus be part of the standard Perl release?

Results (109 votes). Check out past polls.

Notices?