Re: decimal to binary conversion need help
by zentara (Cardinal) on Jan 06, 2005 at 12:16 UTC
|
Update: Corrected. Number needs to be as "string".
#!/usr/bin/perl
use Math::BigInt;
my $bignum = Math::BigInt->new('9007199254740991');
print $bignum->as_bin(),"\n";
I'm not really a human, but I play one on earth.
flash japh
| [reply] [d/l] |
|
|
use bigint;
my $bignum = 9007199254740991;
print $bignum->as_bin(),"\n";
but then all numbers are BigInts, that might lead to a slower script. | [reply] [d/l] |
|
|
I don't know what the restrictions are with "use bigint", but it dosn't give the same result.???? Differ by 1.
#!/usr/bin/perl
use Math::BigInt;
my $bignum = Math::BigInt->new(9007199254740991);
print $bignum->as_bin(),"\n";
########################################################
use bigint;
my $bignum = 9007199254740991;
print $bignum->as_bin(),"\n";
__END__
Results:
0b11111111111111111111111111111111111111111111111111110
0b11111111111111111111111111111111111111111111111111111
I'm not really a human, but I play one on earth.
flash japh
| [reply] [d/l] [select] |
|
|
|
|
|
Re: decimal to binary conversion need help
by BrowserUk (Patriarch) on Jan 06, 2005 at 12:51 UTC
|
If that example was chosen because it is the biggest number you will be dealing with, then you could get away with wrapping this into a function:
my $n = 9007199254740991;
my( $hi, $lo ) = ( int( $n / 2**32 ), $n % 2**32 );
printf "%b%032b\n", $hi, $lo;
11111111111111111111111111111111111111111111111111111
$n--;
( $hi, $lo ) = ( int( $n / 2**32 ), $n % 2**32 );
printf "%b%032b\n", $hi, $lo;
11111111111111111111111111111111111111111111111111110
$n+=2;
( $hi, $lo ) = ( int( $n / 2**32 ), $n % 2**32 );
printf "%b%032b\n", $hi, $lo;
100000000000000000000000000000000000000000000000000000
but if your numbers get much bigger than 253, then you'll need to take the hit of using one of the bigInt libraries.
Examine what is said, not who speaks.
Silence betokens consent.
Love the truth but pardon error.
| [reply] [d/l] |
Re: decimal to binary conversion need help
by ambrus (Abbot) on Jan 06, 2005 at 13:13 UTC
|
And, just for fun, here's a very slow pure perl version that does not depend on arithmetic ops.
#!perl
use warnings;
use strict;
# arithmetic operations on (nonegative) binary numbers
sub addbin0 {
my($a,$b) = @_;
$a || $b ?
( chop($a) ?
(chop($b) ? addbin1($a, $b) . "0" : addbin0($a, $b) . "1") :
(chop($b) ? addbin0($a, $b) . "1" : addbin0($a, $b) . "0") ) :
"";
}
sub addbin1 {
my($a,$b) = @_;
$a || $b ?
( chop($a) ?
(chop($b) ? addbin1($a, $b) . "1" : addbin1($a, $b) . "0") :
(chop($b) ? addbin1($a, $b) . "0" : addbin0($a, $b) . "1") ) :
"1";
}
sub addbin {
addbin0(@_) || "0";
}
# multiplication algorithm to convert decimal number to binary
our @dec2bin1 = qw(0 1 10 11 100 101 110 111 1000 1001);
sub dec2bin {
$_[0]=~/^\s*(-?)(\d+)/ or do {
warn "dec2bin can not interpret its first argument as
+decimal";
return "0";
};
my($sgn, $dec) = ($1, $2);
$dec=~/(\d)/g or die "internal error"; # this regexp always ma
+tches
my $b = $dec2bin1[$1];
while($dec=~/(\d)/g) {
$b = addbin($b . "0", $b . "000"); # multiply by 1010b
$b = addbin($b, $dec2bin1[$1]);
}
$sgn . $b;
}
# convert a number
print dec2bin($ARGV[0]), "\n";
__END__
Update: changed sub dec2bin above by merlyn's suggestion.
Well, it still doesn't check for nonnumeric junk at the end of string, sorry.
Original sub:
# multiplication algorithm to convert decimal number to binary
our @dec2bin1 = qw(0 1 10 11 100 101 110 111 1000 1001);
sub dec2bin {
$_[0]=~/^(-?)(\d*)/;
my($sgn, $dec) = ($1, $2);
$dec=~/(\d)/g;
my $b = $dec2bin1[$1];
while($dec=~/(\d)/g) {
$b = addbin($b . "0", $b . "000"); # multiply by 1010b
$b = addbin($b, $dec2bin1[$1]);
}
$sgn . $b;
}
| [reply] [d/l] [select] |
|
|
sub dec2bin {
I don't see any "decimal" operations in there. That's just "num2bin". Take a number, and create a binary string from it.
In fact, this whole thread has made that common mistake. You aren't converting any "decimal" anywhere. Just because Perl knows how to take a string of decimal digits during parse to create a number internally doesn't mean your subroutine can deal with "decimal" numbers. It's Perl, not you.
update:
Oooh, I missed the "bad use of $1" before as well. Never never never use $1 except in the condition of the previous match.
| [reply] [d/l] |
|
|
You aren't converting any "decimal" anywhere.
Sure we are. He's converting the decimal representation of a number to a binary representation of the same number. Also, since we all deal with representations of numbers to do arithmetic (computers included), I find your pedantery somewhat boring.
thor
Feel the white light, the light within
Be your own disciple, fan the sparks of will
For all of us waiting, your kingdom will come
| [reply] |
|
|
|
|
|
|
|
|
Hello, merlyn. Basically, you are right here.
Numbers are one thing, and representations are an other, so
saying "convert a decimal number to a binary one" might not
be a very precise phrase. I admit that I may be prone
to this kind of error sometimes.
I, however, have to disagree with your reply
in this particular case.
Most solutions in this thread, or indeed, most solutions
that would come into your mind if someone asks this
questions indeed work by first converting the decimal
representation of a number to an internal form, than
converting that number to binary form.
The internal for may be based on binary, or it may be based
on decimal, but this is not important to the user.
(If I'm not much mistaken, binary representation of
bignums are used in ruby and mathematica; decimal
ones in perl's Math::BigInt, dc or bc.)
The paricular node you've replied to, however,
is different. I am not using any internal representations,
nor do I use readily provided (by the CPU, Perl, a module,
or any other software) arithmetic operations on those.
If you read my code, you'll see that the numbers
here are always in the form of a srting, more
precisely either a decimal or a binary representation of it.
(You may count the subroutines on the stack as a different
representation if you really want.)
All I'm doing with these representations is string
operations (provided by perl), and a single indexing an
array by a digit.
Again, I never convert neither the whole number,
nor parts of it to numeric forms understood by the cpu or
perl or any perl module, I am implementing all numeric
operations by hand.
You also mention that you don't see any decimal operations
in this code. This is because they are not needed:
to convert from one representation of a number to an other,
you can either do divisions on the first representation,
or multiplications on the other.
I have chosen the second one, so I do only binary operations;
the only decimal operation I do is take the decimal number
to digits, and index a lookup array with each.
Note that this decision of using multiplication or division
is usually given by what representation of numbers you use
internally.
With current cpus, you store numbers in (binary) fixnums,
and we can do fast arithmetic on those,
so we use binary multiplication to convert
from decimal to fixnum (see perl-5.8.5/toke.c:8047),
and binary division to convert fixnum to decimal
(see perl-5.8.5/sv.c:8956).
A bignum library with decimal representation would,
of course, use
decimal division to convert to binary (bc-1.06/lib/number.c:bc_out_long:1521),
and decimal multiplication to convert from binary (bc-1.06/bc/execute.c:push_constant:644).
(These could be mixed in theory, even a decimal bignum
library could include some binary bignum operations
or vice versa, if that helped converting numbers faster.)
If you look at my program like this, this program
does arithmetic operations in binary, so its internal
form is binary. Thus, if you don't like the name dec2bin,
it should really be called dec2num, not num2bin,
as it converts from decimal to internal numeric form.
I, however, don't think I use either binary or decimal as
an internal numeric form, so I think
I can call it dec2bin.
As for the unchecked regexp matches, you are right,
I should indeed chack them. I am, however, lazy,
and for a quick demonstration such as this, didn't really
care about that. If you give a non-numeric argument
to dec2bin, the regexp match of $dec=~/(\d)/g
will fail, and the value of $1 will be undefined (not undef).
This is a bug, and I'll correct it.
Update: next time, I'll think before I post something.
| [reply] [d/l] |
Re: decimal to binary conversion need help
by ambrus (Abbot) on Jan 06, 2005 at 12:09 UTC
|
| [reply] |
|
|
thank you but i need a perl code
thank u
| [reply] |
|
|
Well, let's use a language with better bigint support. Yes, I know
about Math::BigInt, but others will tell you about that anyway,
so I'll show other solutions. For these,
you have to install respective software
(dc, bc, ruby)
if you don't already have it.
perl -we '"38"=~/(-?)(\d+)/ and $decimal = ($1?"_":"").$2; `dc -e 2o${
+decimal}p` =~ /(-?[01]+)/ and $binary = $1; print $binary, "\n";'
perl -we '"9007199254740991"=~/(-?\d+)/ and $decimal = $1; `echo obase
+=2\\;${decimal} | bc` =~ /(-?[01]+)/ and $binary = $1; print $binary,
+ "\n";'
perl -we '"9007199254740991"=~/(-?\d+)/ and $decimal = $1; `ruby -e\47
+printf(%[%b],\$*[0])\47 ${decimal}` =~ /(-?[01]+)/ and $binary = $1;
+print $binary, "\n";'
| [reply] [d/l] |