A third scheme could implement a little trick to speed up the conversion by looking for consecutive patches of 1s in the input string... So, let's say we have a number like this: "1111111111110000000000" In this case, we could calculate 2^22 and then subtract 2^10 like so:
10000000000000000000000 = 4194304 - 10000000000 = 1024 --------------------------------------- 1111111111110000000000 = 4193280 <= This is the result we're looking + for!
The idea is that performing a single subtraction would be faster than performing an addition every time we encounter a '1' digit in the input string. But I'm not sure how much time this would gain. And the gain would be absolutely non-existent for numbers like "1010101011101010101000101010101010101010000000000101010100101010101001101100000101010101" in which there aren't too many repeating 1s.
#!/usr/bin/perl -w use strict; use warnings; $| = 1; RunTests( '', '0', 'what?', '0', '0', '0', '1', '1', '11', '3', '0001', '1', '1011', '11', '1111', '15', '11111111', '255', 'yay 1__1 Lol', '3', '11111111111111111111111111111111', '4294967295', '10101010101010101010101010101010', '2863311530', '00000000001111111111110000000000', '4193280', '100011111111110011111011001101000', '4831442536', + # 33-bit value '11111111111000111111111100111110110010001000110', '1406773524818 +62', # 47-bit value '111111111111000000000000000000000000000000000000', '281406257233 +920', # 48-bit value '1111111111110000000000000000000000000000000000000', '56281251446 +7840', # 49-bit value '0000111000111000111000111000111000111000111000111000111000111000 +', '1024819115206086200', # 60-bit value '1111111111111111100000000000000001111111111111111000000000000000 +', '18446603338368647168', # 64-bit value '1100111100100110000001111110111000110101010101010101010101010101 +', '14926626734644483413', # 64-bit value '1111111111111111111111111111111111111111111111111111111111111111 +', '18446744073709551615', # 64-bit value '1000000000000000000000000000000000000000000000000000000000000000 +0', '18446744073709551616', # 65-bit value # 112-bit value: '1111111111111111111111111111111111111111111111111111111111111111 +111111111111111111111111111111111111111111111111', '51922968585348276 +28530496329220095', '1000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000', '5192296858534827 +628530496329220096', # 360-bit value: '1111111111111111111111111111111111111111111111111111111111111111 +111111111111111111111111111111111111111111111111111111111111111111111 +111111111111111111111111111111111111111111111111111111111111111111111 +111111111111111111111111111111111111111111111111111111111111111111111 +111111111111111111111111111111111111111111111111111111111111111111111 +11111111111111111111', '234854258277383322788948059678933702737568254 +8908319870707290971532209025114608443463698998384768703031934975', # 1500-bit value: '1000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000', '175373310 +552170193738137939801404289967620079401654144120378990123954819252816 +611018285404432924846308265752033977187586996472744707349798770855194 +590023504239449782426645486322434013557917314732683410921700693147256 +777291324731712626918096946574803223325262758757211677546245866805651 +778980548549427903371569771051088289237163133803665023766376585960668 +373517816863916485209966135263316668342549760000875266777645294402170 +91269193357761841856604274688' ); print "\nDon't panic. Your computer did not crash.\nThe following oper +ation may take a few seconds.\n"; print "\nConverting 4096-digit binary number to decimal using Bin2Dec( +) and Bin2BigInt()\nPlease wait..."; # Generate a 4096-digit binary number: RunTests('1' . '0' x 4096, '104438888141315250669175271071662438257996 +424904738378038423348328395390797155745684882681193499755834089010671 +443926283798757343818579360726323608785136527794595697654370999834036 +159013438371831442807001185594622637631883939771274567233468434458661 +749680790870580370407128404874011860911446797778359802900668693897688 +178778594690563019026094059957945343282346930302669644305902501597239 +986771421554169383555988529148631823791443449673408781187263949647510 +018904134900841706167509366833385055103297208826955076998361636941193 +301521379682583718809183365675122131849284636812555022599830041234478 +486259567449219461702380650591324561082573183538008760862210283427019 +769820231316901767800667519548507992163641937028537512478401490715913 +545998279051339961155179427110683113409058427288427979155484978295432 +353451706522326906139490598769300212296339568778287894844061600741294 +567491982305057164237715481632138063104590291613692670834285644073044 +789997190178146576347322385026725305989979599609079946920177462481771 +844986745565925017832907047311943316555080756822184657174637329688491 +281952031745700244092661691087414838507841192980452298185733897764810 +312608590300130241346718972667321649151113160292078173803343609024380 +4708340403154190336'); print "\nConverting 8192-digit binary number to decimal using Bin2Dec( +) and Bin2BigInt()\nPlease wait..."; # Generate a 8192-digit binary number: RunTests('1' . '0' x 8192, '109074813561941592946298424473378286244826 +416199623269243183278618972133184911929521626423452520198722395729179 +615702527310987082017718406361097976507755479907890629884219298953860 +982522804820515969685161359163819677188654260932456012129055390188630 +101790025253579991720001007960002653583680090529780588095235050163019 +547565391100531236456001484742603529355124584392891875276869627934408 +805561751569434994540667782514081490061610592025643850457801332649356 +583604724240738244281224513151775751916489922636574372243227736807502 +762788304520650179276170094569916849725787968385173704999690096112051 +565505011556127149149251534210574896662954703278632150573082843022166 +497032439613863525162640951616800542762343599630892169144618118740639 +531066540488573943483287742816740749537099351186875635997039011702182 +361674945862096985700626361208270671540815706657513728102702231092756 +491027675916052087830463241104936456875492096732298245918476342738379 +027244843801852697776494107271561158043469082745933999196141424274141 +059911742606055648376375631452761136265862838336862115799363802087853 +767554533678991569423443395566631507008721353547025567031200413072549 +583450835743965382893607708097855057891296790735278005493562156109079 +584517295411597292747987752773856000820411855893000477774872776185381 +351049384058186159865221160596030835640594182118971403786872621948149 +872760365361629885617482241303348543878532402475141941718301228107820 +972930353737280457437209522870362277636394529086980625842235514850757 +103961938744962986680818876966281577815307939317909314364834076173858 +181956300299442279075495506128881830843007964869323217915876591803556 +521615711540299212027615560787310793747746684152836298770869945015203 +123186259420308569383894465706134623670423402682110295895495119708707 +654618662279629453645162075650935101890602377382153953277620867697858 +973196633030889330466516943618507835064156833694453005143749131129883 +436726523859540490427345592872394952522718461740436785475461047437701 +976802557660588103807727070771794222197709038543858584409549211609985 +253890397465570394397308609093059696336076752996493841459818570596375 +456149735582781362383328890630900428801732142480866396267133352800923 +275835087305961411872378142210146019861574738685509689608918918044133 +955852482286754111321263879367556765034036297003193002339782846531854 +723824423202801518968966041882297600081543761065225427016359565087543 +385114712321422726660540358178146909080657646895058766199718650566547 +5715792896'); print "\nNow we will convert 5000 random 128-bit binary numbers using +Bin2BigInt().\nPress ENTER to begin..."; $a = <STDIN>; my $DEC; my $TIME = time; for (my $count = 0; $count < 5000; $count++) { my $random = ''; for (my $bits = 0; $bits < 128; $bits++) { $random .= (rand(300) > 150) ? '1' : '0'; } $DEC = Bin2BigInt($random); print "\n $random => $DEC"; } print("\n", time - $TIME, ' secs.'); print "\n\nNow we will convert 5000 random 128-bit binary numbers usin +g Bin2Dec().\nPress ENTER to begin..."; $a = <STDIN>; $TIME = time; for (my $count = 0; $count < 5000; $count++) { my $random = ''; for (my $bits = 0; $bits < 128; $bits++) { $random .= (rand(300) > 150) ? '1' : '0'; } $DEC = Bin2Dec($random); print "\n $random => $DEC"; } print("\n", time - $TIME, ' secs.'); print "\n\n"; exit; #################################################################### # RUN TESTS: # sub RunTests { my $i = 0; my $ERR = 0; while ($i < @_) { my $THIS_OK = 1; my $BIN = $_[$i++]; my $CORRECT = $_[$i++]; my $DEC1 = Bin2Dec($BIN); my $DEC2 = Bin2BigInt($BIN); if ($CORRECT ne $DEC1) { print "\nBin2Dec('$BIN') outputs:\n$DEC1 when it should be:\n$CO +RRECT\n"; $THIS_OK = 0; $ERR++; } if ($CORRECT ne $DEC2) { print "\nBin2BigInt('$BIN') outputs:\n$DEC2 when it should be:\n +$CORRECT\n"; $THIS_OK = 0; $ERR++; } $THIS_OK and print "\nOK $DEC1"; } print "\n\n $ERR ERRORS.\n\n"; return !$ERR; } #################################################################### # # This function takes a binary number of any size made up of # 1s and 0s and returns a decimal number (base 10). # # This function can convert a 64-bit or 128-bit binary number to # a decimal number even when 32-bit processor is used. Regardless # of processor architecture, it will work on any machine. # # The input string can contain any number of digits. Any character # other than 1s and 0s is going to be ignored. The output number # is going to be a big integer which may contain hundreds or # even thousands of digits. # # Usage: STRING = Bin2Dec(STRING) # sub Bin2Dec { defined $_[0] or return 0; my $B = $_[0]; $B =~ tr|01||cd; # Remove illegal chars $B =~ s/^0+//; # Remove preceding zeros (my $L = length($B)) or return 0; # Return 0 $L > 32 or return oct('0b' . $B); # Is it 32 bits or less? my $DEC = oct('0b' . substr($B, -32)); # Convert last 32 bits $B = substr($B, 0, -32); # Remove last 32 bits # Convert number up to 49 bits: $L < 50 and return $DEC + oct('0b' . $B) * 4294967296; my $i; my $N; my $PWR = "\x06\x09\x02\x07\x06\x09\x04\x09\x02\x04"; # 4294967296 $DEC =~ tr|0-9|\x00-\x09|; $DEC = reverse($DEC); $L -= 32; my $PWR2 = 4294967296; while ($L-- >= 0) { if (chop($B)) # Is the next binary digit a '1' ? { # Perform simple addition: $DEC += $PWR $i = (length($PWR) >> 2) + 2; while ($i-- > 0) { vec($DEC, $i, 32) += vec($PWR, $i, 32); } # Perform carry operation: while ($DEC =~ s/([^\x00-\x09])(.)/ $N = ord($1); pack('CC', cho +p($N), $N + ord($2)) /esg) {} $DEC =~ s/([^\x00-\x09])$/ $N = ord($1); pack('CC', chop($N), $N +) /es; } # Here we calculate the next power of two. # We shift each byte of $PWR to the left by 1. # The fastest way to do this is using the tr/// operator. # Each digit 0-9 is represented as an ASCII character # from \0 to \x09 and so once shifted, the numbers then # become \x00 to \x12. After this, we perform a carry operation. # Note: $PWR stores numbers backwards, so "4096" would be # represented as "\x06\x09\x00\x04". # Multiply each digit by 2: $PWR =~ tr|\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0C\x0E\x1 +0\x12\x14\x18\x1C\x20\x24\x28\x30\x38\x40\x48\x70|\x00\x02\x04\x06\x0 +8\x0A\x0C\x0E\x10\x12\x14\x18\x1C\x20\x24\x28\x30\x38\x40\x48\x50\x60 +\x70\x80\x90\xE0|; # Next, we perform the carry operation again: while ($PWR =~ s/([^\x00-\x09]{1})(.)/ $N = ord($1); pack('CC', ch +op($N), $N + ord($2)) /esg) {} $PWR =~ s/([^\x00-\x09]{1})$/ $N = ord($1); pack('CC', chop($N), $ +N) /es; } $DEC =~ tr|\x00-\x09|0-9|; $DEC =~ s/0+$//; $DEC = reverse($DEC); return $DEC; } #################################################################### # # This function converts a binary number from base 2 to base 10 # using BIGADD() function which is slower. # Accepts any number of digits. # # Usage: STRING = Bin2BigInt(STRING) # sub Bin2BigInt { my $N = defined $_[0] ? $_[0] : ''; $N =~ tr|01||cd; # Remove everything except 1s and 0s $N =~ s/^0+//; # Remove initial zeros my $L = length($N); if ($L == 0) { return '0'; } if ($L <= 32) { return oct('0b' . $N); } my $OUTPUT = oct('0b' . substr($N, -32)); my $PWR = 4294967296; $L -= 32; while ($L--) { if (length($PWR) < 15) { if (vec($N, $L, 8) == 49) { $OUTPUT += $PWR; } $PWR += $PWR; } else { if (vec($N, $L, 8) == 49) { $OUTPUT = BIGADD($OUTPUT, $PWR); } $PWR = BIGADD($PWR, $PWR); } } return $OUTPUT; } #################################################################### # # This function adds two big positive integers in base 10 and # returns the sum. There is no error checking done, so make sure # to only provide digits in the arguments. Any non-digit character # will mess up the output. # # The 1st and 2nd arguments must contain two big integers that have # to be added. The 3rd and 4th arguments shift these integers to # the left or right before the addition. For example: # BIGADD(4, 5, 1, 0) would shift 4 to the right by 1, # so it would become 40, and then 40 + 5 = 45. # # Usage: BIGINT_SUM = BIGADD(BIGINT_A, BIGINT_B, SHIFT_A, SHIFT_B) # sub BIGADD { no warnings; my $A = defined $_[0] ? $_[0] : ''; my $B = defined $_[1] ? $_[1] : ''; $A =~ s/^0//g; $A =~ tr|0-9||cd; $B =~ s/^0//g; $B =~ tr|0-9||cd; my $AL = length($A) + int($_[2]); my $BL = length($B) + int($_[3]); my $P = ($AL > $BL ? $AL : $BL) + 1; my $CARRY = 0; my $SUM = ''; while ($P--) { my $DIGIT = (($CARRY >> 1) & 1) + (vec($A, --$AL, 8) & 15) + (vec($B, --$BL, 8) & 15); vec($SUM, $P, 8) = $DIGIT + ($CARRY = ($DIGIT > 9) ? 38 : 48); } $SUM =~ s/^0+//; # Discard preceding zeros return (length($SUM)) ? $SUM : 0; }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: converting binary to decimal
by tybalt89 (Monsignor) on Jun 06, 2025 at 04:16 UTC | |
by harangzsolt33 (Deacon) on Jun 26, 2025 at 17:33 UTC | |
by ysth (Canon) on Jun 26, 2025 at 19:23 UTC | |
by hippo (Archbishop) on Jun 26, 2025 at 17:59 UTC | |
by harangzsolt33 (Deacon) on Jun 27, 2025 at 03:15 UTC | |
by tybalt89 (Monsignor) on Jun 26, 2025 at 19:41 UTC | |
by harangzsolt33 (Deacon) on Jun 27, 2025 at 03:13 UTC | |
by tybalt89 (Monsignor) on Jun 27, 2025 at 04:08 UTC | |
| |
Re: converting binary to decimal
by hippo (Archbishop) on Jun 05, 2025 at 18:48 UTC | |
by LanX (Saint) on Jun 06, 2025 at 14:02 UTC | |
by LanX (Saint) on Jun 05, 2025 at 20:09 UTC | |
by harangzsolt33 (Deacon) on Jun 06, 2025 at 01:30 UTC | |
by harangzsolt33 (Deacon) on Jun 06, 2025 at 01:29 UTC | |
by hippo (Archbishop) on Jun 06, 2025 at 08:53 UTC | |
by Anonymous Monk on Jun 06, 2025 at 14:51 UTC | |
by pryrt (Abbot) on Jun 06, 2025 at 17:49 UTC | |
| |
Re: converting binary to decimal
by tybalt89 (Monsignor) on Jun 06, 2025 at 11:01 UTC | |
by Anonymous Monk on Jun 06, 2025 at 14:46 UTC | |
by LanX (Saint) on Jun 06, 2025 at 15:06 UTC | |
by harangzsolt33 (Deacon) on Jun 06, 2025 at 17:51 UTC | |
by LanX (Saint) on Jun 06, 2025 at 21:57 UTC | |
| |
by tybalt89 (Monsignor) on Jun 06, 2025 at 14:51 UTC | |
by Anonymous Monk on Jun 06, 2025 at 15:00 UTC | |
by tybalt89 (Monsignor) on Jun 06, 2025 at 15:28 UTC | |
by afoken (Chancellor) on Jun 06, 2025 at 15:52 UTC | |
|