designerdecimal

find a decimal representation of your name, and the rational approximation thereof
git clone https://wehaveforgeathome.hates.computer/designerdecimal.git
Log | Files | Refs | LICENSE

designerdecimal.pl (1505B)


      1 #!/usr/bin/perl
      2 
      3 # For describing a performant rational approximation algorithm, thanks to:
      4 # John Kennedy, "Algorithm to Convert a Decimal to a Fraction"
      5 # http://homepage.smc.edu/kennedy_john/DEC2FRAC.PDF
      6 
      7 use strict;
      8 use warnings;
      9 use Math::BigFloat;
     10 
     11 my $name = "Santa Claus";
     12 if (scalar(@ARGV) > 0) {
     13   $name = join(' ', @ARGV);
     14 }
     15 
     16 my @chars = split(//, $name);
     17 my $ascii = '';
     18 foreach my $char (@chars) {
     19   $ascii .= sprintf('%03s' , ord($char));
     20 }
     21 $ascii = '1.' . $ascii . '004';
     22 my $accuracy = length($ascii) - 1;
     23 
     24 my $x = Math::BigFloat->new($ascii);
     25 $x->accuracy($accuracy);
     26 my $z = $x->copy();
     27 my $dMinTwo = Math::BigFloat->bzero();
     28 my $d = Math::BigFloat->bone();
     29 my $n = Math::BigFloat->bzero();
     30 my $i = 0;
     31 
     32 print "For the name '$name':\n  Your designer decimal is $ascii\n";
     33 my $q = $n->copy();
     34 $q->bdiv($d);
     35 $q->accuracy($accuracy);
     36 
     37 until (BigFloatEqual($q, $x)) {
     38   my $zInt = $z->copy();
     39   $zInt->bfloor();
     40   my $zSub = $z->copy();
     41   $zSub->bsub($zInt);
     42   $z = Math::BigFloat->bone();
     43   $z->bdiv($zSub);
     44 
     45   $zInt = $z->copy();
     46   $zInt->bfloor();
     47 
     48   my $dCpy = $d->copy();
     49   $d->bmul($zInt->as_int());
     50   $d->badd($dMinTwo);
     51   $dMinTwo = $dCpy->copy();
     52 
     53   $n = $d->copy();
     54   $n->bmul($x);
     55   $n->bfround(0, 'odd');
     56 
     57   $q = $n->copy();
     58   $q->round_mode('trunc');
     59   $q->accuracy($accuracy);
     60   $q->bdiv($d);
     61 
     62   $i++;
     63 }
     64 
     65 print "  Your rational approximation is $n / $d\nTook $i iterations.\n";
     66 
     67 sub BigFloatEqual {
     68   my ($x, $y) = @_;
     69   if ($x->bcmp($y) == 0) {
     70     return 1;
     71   }
     72   return 0;
     73 }