2013-01-05 92 views
0

如何將Perl中的數字編碼爲8個字符以字母開頭並以結尾數字爲校驗位的數字結尾的字母數字字符串。在Perl中將大整數轉換爲字母數字字符串

那麼如何生成校驗位,我打算從21767823360開始計數,這樣我的結果字符串以A000000開頭,但是perl並沒有計算這麼大的數字。

請提出解決方案。

$AppID=alphanumero($appid,8,1); 

sub alphanumero{ 
my ($n,$length,$type)[email protected]_; 
my @to_b36 = (0 .. 9, 'A' .. 'Z'); 
use integer; # so that /= 36 is easy 
my $u=$n%10;$n=21767823360+($n-$u)/10; 
my $t = "";do { $t = $to_b36[$n % 36] . $t, $n /= 36 } while $n; 
return "$t$u"; 
} 
+3

莫非你展示你試過的代碼? –

+0

@divid添加的代碼,我試過.. –

回答

4

Perl有大的數字小問題,如果你的號碼真的是巨大的,只是use bignum。這透明地啓用無限精度算術。

您的號碼21767823360需要大約35位。我的perl使用64位整數構建(請參閱perl -v以檢查您的支持),因此您的電話號碼對我來說不是「太大」。

的算法將數字轉換到基座-n是簡單:

# pseudocode 
let "digits"   be the array containing all the digits of our representation. 
         # the size of digits is the base of our new representation 
         # the digits are sorted in ascending order. 
         #digits[0] is zero. 
var "n"    is the number we want to represent. 
var "size"   is the number of digits of the new representation. 
         # floor(ln(n)/ln(digits.size)) 
var "representation" is the empty string. 
while size >= 0: 
    representation ← representation.concat(digits[n/digits.length^size]). 
    n    ← n.modulo(digits.length^size). 
    size   ← size - 1. 
return representation. 

實施例的Perl:

#!/usr/bin/perl 
use strict; use warnings; 
use Carp; 

sub base_n { 
    my ($number, $base, $max_digits, $pad) = @_; 
    defined $number or croak "Undefined number for base_n"; 
    $number == int $number and $number >= 0 
        or croak "The number has to be a natural number for base_n"; 
    defined $base or croak "Undefined base for base_n"; 
    $base == int $base and $base > 0 
        or croak "The base has to be a positive integer for base_n"; 

    my @digits = (0 .. 9, "A" .. "Z"); 
    $base <= @digits or croak "base_n can only convert to base-" . @digits . " max."; 
    @digits = @digits[0 .. $base - 1]; 

    my $size = $number ? int(log($number)/log($base)) : 0; # avoid log(0) 
    if (defined $max_digits) { 
    $size < $max_digits 
     or croak "The number $number is too large for $max_digits digits in base $base."; 
    $size = $max_digits - 1 if $pad; 
    } 

    my $representation = ""; 
    while ($size >= 0) { 
    $representation .= $digits[$number/@digits**$size]; 
    $number   %= @digits**$size; 
    $size--; 
    } 

    if (wantarray) { 
    my $checksum = substr $representation, -1; 
    return $representation, $checksum; 
    } else { 
    return $representation; 
    } 
} 

相應的(但不完全)的單元測試:

use Test::More; 
my $n = 21767823360; 
ok "A000000" eq base_n($n => 36),  "simple"; 
ok "A000000" eq base_n($n => 36, 8),  "valid constraint"; 
ok "0A000000" eq base_n($n => 36, 8, 1), "padding"; 
ok ! eval { base_n($n => 36, 6); 1 }, "invalid constraint"; 
ok "0" eq (base_n($n => 36))[1],   "checksum (1)"; 
ok "A" eq (base_n($n+10 => 36))[1],  "checksum (2)"; 
ok "0" eq base_n(0 => 36),    "zero: simple"; 
ok "0"x8 eq base_n(0 => 36, 8, 1),  "zero: padding"; 
ok ! eval { base_n($n => 0.7); 1 },  "invalid base"; 
ok ! eval { base_n(0.7 => 36); 1 },  "invalid number"; 
ok $n == base_n($n => 10),    "round-trip safety"; 
ok $n eq base_n($n => 10, length $n, 1), "round-trip safety: padding"; 
done_testing; 
+0

真棒....我嘗試這個,希望它會工作好:) –

相關問題