2013-01-05 3 views
0

숫자를 Perl에 8 자로 인코딩하는 방법 알파벳으로 시작하고 끝자리 숫자가 숫자 인 숫자로 끝나는 영숫자 문자열.큰 정수를 Perl의 영숫자 문자열로 변환하십시오.

그래서 체크 디지트를 생성하는 방법과 21767823360에서 카운터를 시작하여 내 결과 문자열이 A000000으로 시작하지만 펄이 계산을 위해 큰 숫자를 차지하지 않도록 계획했습니다.

해결 방법을 제안하십시오.

$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

펄은 큰 숫자와 작은 문제가, 당신의 숫자는 정말 큰 단지 use bignum 경우. 이것은 무한 정밀도의 산술을 투명하게 가능하게합니다.

귀하의 전화 번호 21767823360은 약 35 비트가 필요합니다. 내 perl은 64 비트 정수 (지원을 확인하려면 perl -v 참조)로 작성되었으므로 전화 번호가 너무 많지 않습니다.

# 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. 

예 펄 :

#!/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; 
    } 
} 

상응 (불완전한) 단위 테스트 :

알고리즘베이스 N은 단순 숫자로 변환하는

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

awesome .... 나는 이것을 시도하고있다. –

관련 문제