Re: Reversed long division
by ikegami (Patriarch) on Jun 29, 2005 at 16:39 UTC
|
use Math::BigFloat ();
$x = Math::BigFloat->new("15000000") / 222;
print("$x\n");
# 67567.56756756756756756756756756756756757
$x = Math::BigFloat->new("67567.57") * 222;
print("$x\n");
# 15000000.54
| [reply] [d/l] [select] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: Reversed long division
by ikegami (Patriarch) on Jun 29, 2005 at 17:27 UTC
|
I worked out a solution, but the problem is that it prepends to $out instead of appending, so converting $out to a file handle is out.
$in = '67567';
$carry = 126;
$out = sprintf('%06d', substr($in, -3, 3, '') * 222 + $carry);
while (length($in)) {
substr($out, 0, 3, sprintf('%04d',
substr($out, 0, 3) + substr($in, -1, 1, '') * 222
));
}
$out =~ s/^0+//;
print($out, "\n");
You'll need to put some work into reversing it. Show some effort.
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: Reversed long division
by tlm (Prior) on Jun 29, 2005 at 22:15 UTC
|
Interesting problem. Here's a straightforward extension of ikegami's solution to work off a file. I post it more for the record than for the OP (who I doubt will find it useful, since using it will require a modicum of honest work ;-) ):
mult takes three arguments: a file, a divisor, and a remainder. The file must contain the quotient (base 10) without any leading 0s or any whitespace anywhere in the file digits of the quotient in reverse order. mult computes the dividend (i.e. the sum of the remainder plus the product of the quotient and the divisor) and puts it, again, with digits in reverse order, in a file whose name is obtained from the name of the input file. The input is read into memory in chunks of size 8192 and processed (though the size of these chunks is easily configurable, by setting the $STRIDE variable).
It processed a file containing a quotient of 1,000,000,000 digits in 35 minutes. Minimally tested, though.
And to the OP, you are welcome to tweak this further to suit your needs.
Update: Fixed the script so that now the digits in the input and output files are in the correct (not reverse) order. Also fixed some lurking bugs relating to mixing sysread calls with seek and tell calls.
| [reply] [d/l] [select] |
Re: Reversed long division
by thundergnat (Deacon) on Jun 29, 2005 at 18:56 UTC
|
Hmmm, an interesting diversion...
Here's my version of both longdiv and longmul with a little test script. Dividing a random 1000 digit number by 222 and then multiplying the result by 222 is accurate to at least 12 decimal places for me. (The inaccuracy is due to the limit of accuracy for the fractional portion of the number while dividing.) And it takes much longer to print the number to the screen than it does to calculate it.
#!/usr/bin/perl
use warnings;
use strict;
my $number;
for(0..999)
{
$number .= int(rand 9);
}
print "$number\n\n";
print longdiv($number, 222) . "\n\n";
print longmul(longdiv($number, 222), 222) . "\n";
sub longdiv {
my @digits = split //, shift;
my $demoninator = shift;
my $carry = 0;
my $out = '';
my $numerator;
while (@digits) {
$numerator = shift @digits;
$numerator += $carry * 10;
$carry = $numerator % $demoninator;
$out .= int($numerator / $demoninator) if @digits;
}
$out =~ s/^0+//;
$out .= ($numerator / $demoninator);
return $out;
}
sub longmul {
my @digits = reverse split //, shift;
my $multiplier = shift;
my $out = '';
my ($digit, $progress);
while (@digits) {
$digit = shift @digits;
if ($digit eq '.')
{
$out = '.' . $out;
next;
}
$progress += $digit * $multiplier;
$out = ($progress % 10) . $out;
$progress = int($progress / 10);
}
$out = $progress . $out;
return $out;
}
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: Reversed long division
by tlm (Prior) on Jun 29, 2005 at 16:48 UTC
|
| [reply] [d/l] |
A reply falls below the community's threshold of quality. You may see it by logging in. |
Re: Reversed long division
by BrowserUk (Patriarch) on Jun 29, 2005 at 19:40 UTC
|
Would this help?
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
| [reply] [d/l] |
Re: Reversed long division
by zentara (Cardinal) on Jun 30, 2005 at 11:52 UTC
|
Have you thought of running "bc" through backticks,expect or IPC? It will handle thousands of digits, and is fast.
I'm not really a human, but I play one on earth.
flash japh
| [reply] |
|
|
I am not so sure, because bc internally calculates in decimal
(at least the GNU version does),
so you'd have to convert the very long base 222 number to
base 10, and the result back, which could take much time.
Of course, there are other bignum libraries apart from bc,
but all of those I know calculates in a fixed base, which
is either a power of 2, or a power of 10.
It's unlikely that you'll find a pre-written bignum
library that uses base 222.
(However, you could still learn much from their code.)
| [reply] |