5 : 25 JavaScriptで巨大整数演算

← 5‒24 p↑ もくじ i 5‒26 n →

JavaScriptで1000桁電卓

2002年 5月25日
記事ID d20525


2002JavaScript bigint.js v0.2 - v0.4  2004 bigint.js v0.5  2596

[JS] 100


JavaScriptPGP24RSAJavaScript253 JavaScript

100桁程度の整数3つを掛け算するデモの光景


253 16100JavaScript


7771234567890 67890, 12345, 777 340
12345 67890 22222 00000 33333 12345 44444 56789
8 BIG_UNIT = 100000 5610210

bigint.js
function bset( canon ) {
    var Work = new Array();
    var size = Math.ceil( canon.length / 5 );

    // 最大要素の桁数
    var len0 = canon.length % 5;
    if(len0==0) len0=5;

    // とりあえず降順に格納。先頭には0がないので必ず十進法で評価される
    Work[0] = eval( canon.substr( 0, len0 ) );

    var pos = len0;
    var tmp;

    for( var i=1; i<size; i++ ) {
        tmp = canon.substr( pos , 5 );
        pos += 5;

        // 数値に変換。必ず十進法で評価されるよう0を消す
        Work[i] = eval( "1" + tmp ) - BIG_UNIT;
    }
    // 昇順にする
    return my_reverse( Work );
}

 bshow() 


badd( A, B ) 2BIG_UNIT1 BIG_UNIT 1

bsign babscmp
function badd( B1, B2 ) {
    var sign1 = bsign(B1), sign2 = bsign(B2);
    var ret_sign;

    // 結果の正負の判定
    if( sign1 * sign2 <0 ) {
        var abscmp = babscmp( B1, B2 );
        if( abscmp > 0 ) ret_sign = sign1;
        else if( abscmp < 0 ) ret_sign = sign2;
        else ret_sign = 1; // 符号だけ異なって絶対値が同じ、和はゼロ

    } else if( sign1 >= 0 ) {
        ret_sign = 1; // 正の数同士の足し算
    } else {
        ret_sign = -1; // 負の数同士の足し算
    }

    var sum = new Array();

    var max = Math.max( B1.length, B2.length );

    for( var i=0; i < max; i++ ) {
        sum[i] = 0;
        if( B1[i] ) sum[i] += B1[i];
        if( B2[i] ) sum[i] += B2[i];
    }

    // くりあがり等
    for( var i=0; i<sum.length; i++ ) {
        if( ret_sign >= 0 ) { // 結果は非負
            while( sum[i] >= BIG_UNIT ) {
                sum[i]-=BIG_UNIT;
                if(typeof sum[i+1] == "number" ) sum[i+1]++;
                else sum[i+1] = 1;
            }
            while( sum[i] < 0 ) { sum[i]+=BIG_UNIT; sum[i+1]--; }
        } else { // 結果は負
            while( sum[i] > 0 ) { sum[i]-=BIG_UNIT; sum[i+1]++; }
            while( sum[i] <= - BIG_UNIT ) {
                sum[i]+=BIG_UNIT;
                if(typeof sum[i+1] == "number" ) sum[i+1]--;
                else sum[i+1] = -1;
            }
        }
    }

    return bset( bshow( sum ) );
}

 bshow  bset 00


 bneg 使
function bsub( B1, B2 ) {
    return ( badd( B1, bneg(B2) ) );
}


3412JavaScript使 badd 使bmul 
function bmul( B1, B2 ) {
    var zeros, _mul;
    var Work = bset("0");

    for( var idx1=0; idx1 < B1.length; idx1++ ) {
        for( var idx2=0; idx2 <B2.length; idx2++ ) {
            zeros = getZeros( ( idx1 + idx2 )*5 );
            _mul = ( B1[idx1] * B2[idx2] ).toString(10) + zeros;
            Work = badd( Work, bset(_mul) );
        }
    }
    return Work;
}

function getZeros( how_many ) {

    var _z = how_many % 10;
    var _z10 = (how_many - _z) / 10;

    var ret = "";

    for( var i = 0; i < _z10; i++ ) ret += "0000000000";
    for( var i = 0; i < _z; i++ ) ret += "0";

    return ret;
}

Demo


A, B, CABA,B,C1020

ABC2Windows 2000 IE6.0Netscape4.79100353

A = 12345 67890 22345 67890 32345 67890 42345 67890 52345 67890 62345 67890 72345 67890 82345 67890 92345 67890
B = 333 33333 33335 55555 55555 00000 00000 00000 00777 77777 77777 77777 77777 77788 88888 88888 44444 44444 44222
X = A+B =333 45679 01225 77901 23445 32345 67890 42345 68668 30123 45668 40123 45668 50134 56779 71234 12335 36790 12112
A = X-B =12345 67890 22345 67890 32345 67890 42345 67890 52345 67890 62345 67890 72345 67890 82345 67890 92345 67890
OK!
B = X-A =333 33333 33335 55555 55555 00000 00000 00000 00777 77777 77777 77777 77777 77788 88888 88888 44444 44444 44222
OK!
X = (A+B)+C =11 11444 56779 01225 77901 26778 65678 00214 00330 58069 40007 55516 55110 64586 91876 41197 20775 97220 65281 18218
Y = A+(B+C) =11 11444 56779 01225 77901 26778 65678 00214 00330 58069 40007 55516 55110 64586 91876 41197 20775 97220 65281 18218
OK!
X = (A*B)*C =457 24736 67040 08535 28521 59731 75098 57851 98732 72216 07382 63656 75462 12291 46674 46059 98307 52619 87597 43724 32377 94439 41806 17489 01610 69323 68417 76537 81637 16605 73585 89499 96060 73430 88742 68657 66261 31020 27937 30357 75150 21930 72184 91569 07868 59150 40102 41205 24915 15855 15963 72042 85290 50770 39540 27480
Y = A*(B*C) =457 24736 67040 08535 28521 59731 75098 57851 98732 72216 07382 63656 75462 12291 46674 46059 98307 52619 87597 43724 32377 94439 41806 17489 01610 69323 68417 76537 81637 16605 73585 89499 96060 73430 88742 68657 66261 31020 27937 30357 75150 21930 72184 91569 07868 59150 40102 41205 24915 15855 15963 72042 85290 50770 39540 27480
OK!
X = (A+B)*C =3705 07544 54359 13580 24672 72016 45760 70208 62626 73290 32358 67811 66471 18914 27745 80607 63768 77462 02779 69691 66999 61942 58478 34043 20661 44378 45529 00907 68299 65553 11252 97441 26123 94130 72547 34217 23471 55872
Y = A*B+A*C =3705 07544 54359 13580 24672 72016 45760 70208 62626 73290 32358 67811 66471 18914 27745 80607 63768 77462 02779 69691 66999 61942 58478 34043 20661 44378 45529 00907 68299 65553 11252 97441 26123 94130 72547 34217 23471 55872
OK!

Cost: 53.316 sec.


RSAJavaScript bmod bpow 

URL



https://yosei.fi/articles/5/25/#d20525


2002525
IDd20525a


JavaScript1000bigint_0_2.js


100100100248163264666432492
// PはBigInt形式でも通常の自然数でもかまわない。
function bpow( B, P ) {
    var power;
    if( typeof P == "number" ) power = P;
    else if( typeof P == "object") power = b2float(P);
    else return null;

    if( power != Math.floor(power) || power > 2048 || power < 0 ) {
        _debug("[ERROR] inadequate power at function bpow(): power=" + power );
        return null
    }

    // 3乗までは直接計算する
    if( power == 0 ) {
        if( babscmp( B, [0] ) == 0 ) return [ 0 ];
        else return [1];
    } else if( power == 1 ) return B;
    else if( power == 2 ) return bmul( B, B );
    else if( power == 3 ) return bmul( bmul( B, B ), B );

    // powerを2進展開する
    var bin_str = power.toString(2);
    var max = bin_str.length - 1;
    var bin_digit = new Array();
    for( var i=0; i<=max ; i++ ) {
        bin_digit[i] = bin_str.charAt( max - i );
    }

    // Bの2^n乗を計算する
    var _B = new Array(); // 配列の配列
    _B[0] = B; // 最初の要素はB自身
    for( var n = 1; n <= max; n++ ) {
        _B[n] = bmul( _B[ n-1 ] , _B[ n-1 ] );
    }

    var Ret = [1];
    for( var i = 0; i < bin_digit.length; i++ ) {
        if( bin_digit[i] == 1 ) Ret = bmul( Ret, _B[i] );
    }

    return Ret;
}


: 2, 4, 8, 16, 32, ... 221000?

21000bpow( [2], [1000] ) 

10 71508 60718 62673 20948 42504 90600 01810 56140 48117 05533 60744 37503 88370 35105 11249 36122 49319 83788 15695 85812 75946 72917 55314 68251 87145 28569 23140 43598 45775 74698 57480 39345 67774 82423 09854 21074 60506 23711 41877 95418 21530 46474 98358 19412 67398 76755 91655 43946 07706 29145 71196 47768 65421 67660 42983 16526 24386 83720 56680 69376.302

Netscape4.79 43.542 

 JavaScript Math.pow( 2 , 1000 ) 
1.0715086071862673e+301
BigInt使



B1B2JavaScript bmul 
function bdivmod( B1, B2 ) {

    var sign2 = bsign( B2 );

    // 第0近似
    var _Q = _b2fdiv2b( B1, B2 );

    var _R = new Array();

    var step;

    for( step=1; step<100; step++ ) {

        // 剰余を求める
        _R = bsub( B1, bmul( B2, _Q ) );

        // 剰余が非負で割る数B2より絶対値が小さければ計算終了
        if( bsign( _R ) >=0 && babscmp( _R, B2 ) < 0 ) return [ _Q, _R ];

        // しからざれば ...
        if( sign2 >= 0 || step%2==0 ) {
            // 残差をB2で割った商を足して_Qを補正
            _Q = badd( _Q, _b2fdiv2b( _R, B2 ) );
        } else {
            // 負数で割る場合、商+1も試さねばならない
            _Q = badd( _Q , [1] );
        }
    }
    _debug("[Error] Too many steps at function bdivmod: _R=" + bshow(_R));
    return null;
}

B2

 _b2fdiv2b BigInt2floatBigInt
function _b2fdiv2b( B1, B2 ) {
    return bset(   Math.floor( b2float(B1)/b2float(B2) ).toString()   );
}

JavaScript2.2220000222222167e+53bset() 
    var part = str.match(/^(\-?)(\d+)\.(\d+)e([\+|\-]\d+)/i);
    if(part) {
        var power = eval( part[4] );
        if( power < 0 ) return "0";

        // part[3] の右端に必要なだけ文字0をつなげる
        // もしpart[3]がe10をかけても小数部分があるなら、小数部分は捨てる
        var c;
        var ret = "";
        for( var i=0; i < power; i++ ) {
            c = part[3].charAt(i) || "0" ;
            ret += c;
        }

        ret = part[2].toString() + ret;
        // マイナス符号
        if( part[1] ) ret = part[1] + ret;

        return ret;
    }


function bdiv( B1, B2 ) {
    var result = bdivmod( B1, B2 );
    return result[0];
}

function bmod( B1, B2 ) {
    var result = bdivmod( B1, B2 );
    return result[1];
}

bdiv  bmod  bdivmod  bdivmod 2bdivmod 010BigIntbshow 使

259-1 ?

JavaScript253259-1BigInt
259-1 = 576 46075 23034 23487
10181041020:
var A=bset("2"), B=bset("59"), C=bset("1");
var N = bsub( bpow( A, B ), C );
var I;

document.write("<p>Checking whether it is divisible by:<br>");
for(var i=100001; i<200000; i+=2 ) {
    if(i%1000==1) document.write( "" + (i-1) + " ...<br>");

    if(i%3==0||i%5==0||i%7==0||i%11==0||i%13==0||i%17==0||i%19==0||
    i%23==0||i%29==0||i%31==0||i%37==0||i%41==0||i%43==0||i%47==0||
    i%53==0||i%59==0||i%61==0||i%67==0||i%71==0||i%73==0||i%79==0||
    i%83==0||i%89==0||i%93==0||i%97==0||i%101==0||i%103==0||i%107==0||
    i%109==0||i%113==0||i%127==0||i%131==0||i%137==0||i%139==0||i%149==0)continue;

    var I = bset( i.toString() );

    if( bmod( N, I ) == 0 ) {
        document.write( " <strong>" + i + "</strong> found!</p>" );
        break;
    }
}

 179951 259-1 
259-1 = 179951×320 34317 80337
 bdiv, bmod 使

()()


RSA69431471917441bpow  bmod 使 bpowmod 
// BのP乗をmodで割ったときの余りを求める
// P, mod はBigInt形式でも数値でもかまわない。
function bpowmod( B, P, mod ) {
    if( !isBigInt(B) ) return null;

    var power;
    if( typeof P == "number" ) power = P;
    else if( typeof P == "object") power = b2float(P);
    else return null;

    if( power != Math.floor(power) || power < 0 ) {
        _debug("[ERROR] inadequate power at function bpowmod(): power=" + power );
        return null
    } else if( power > Math.pow(2, 52) ) {
        _debug("[NOT IMPLEMENTED YET] a big power at function bpowmod(): power=" + power );
        return null
    }

    var M = new Array();
    if( typeof mod == "number" ) M = bset( mod.toString(10) );
    else if( isBigInt( mod ) ) M = bcopy( mod );
    else return null;

    var fmod = b2float(M);
    // modは2以上でなければならない
    if( fmod <= 1 ) {
        _debug("[ERROR] inadequate mod at function bpowmod(): mod=" + bshow(M) );
        return null
    }

    // 0乗と1乗は直接計算
    if( power == 0 ) {
        if( babscmp( B, [0] ) == 0 ) return [ 0 ];
        else return [1];
    } else if( power == 1 ) return bmod( B, M );

    // powerを2進展開する
    var bin_str = power.toString(2);
    var max = bin_str.length - 1;
    var bin_digit = new Array();
    for( var i=0; i<=max ; i++ ) {
        bin_digit[i] = bin_str.charAt( max - i );
    }

    // Bの2^n乗をMで割った剰余計算する
    var _B = new Array(); // 配列の配列
    _B[0] = bmod( B, M );
    for( var n = 1; n <= max; n++ ) {
        _B[n] = bmod( bmul( _B[ n-1 ] , _B[ n-1 ] ) , M );
    }

    var Ret = [1];
    for( var i = 0; i < bin_digit.length; i++ ) {
        if( bin_digit[i] == 1 ) Ret = bmod( bmul( Ret, _B[i] ), M );
    }

    return Ret;
}


: 69431471917441

RSA
var answer = bpowmod( [6943], [14719], [17441] );
4980


JavaScript使JavaScript
"BigInt"ライブラリ関数 (Ver.0.2)
bset(str) 文字列strの形で与えられた巨大整数を一定の形式の配列(以下BigInt形式と仮称)に格納、その配列を返す。メモリが許す限り無制限の桁数の数を格納できる。
bshow(B) BigIntオブジェクトBを通常の十進数としての自然な文字列で返す。
badd(A,B) 2つの巨大整数AとBの和を返す。
bsub(A,B) AからBを引いた差を返す。
bmul(A,B) AとBの積を返す。
bdiv(A,B) AをBで割った整数商を返す。
bmod(A,B) AをBで割った余りを返す。
bdivmod(A,B) 商と余りを同時に(長さ2の配列に入れて)返す。
bpow(A,P) AのP乗を返す。
bpowmod(A,P,M) AのP乗をMで割った余りを返す。
bsign(A) Aが負のとき負の数を、そうでなければ負でない数を返す。
bneg(A) Aと絶対値が等しく符号が反対のオブジェクトを返す。
babscmp(A,B) AとBの絶対値を比較して、Aのほうが大きければ正の数、Aのほうが小さければ負の数、等しければ0を返す。
b2float(A) Aを浮動小数点数にキャストして返す。戻り値はJavaScriptで数としてそのまま使えるが、Aの絶対値が253を越えている場合、精度が失われる。
bcopy(B) Bと等しいBigInt配列を作って返す。コピーをいじってもオリジナルのBには影響しない。
isBigInt(B) Bが形の良いBigIntオブジェクトならtrueを返す。そうでなければfalseを返す。
bdigit(B) Bの桁数(十進法)を返す。

問題


使3264RSAJavaScript

URL



https://yosei.fi/articles/5/25/#d20525a


bigint_0_4.js 

2002530
IDd20530


BigIntJavaScript253
document.write( Math.pow( 7, 20 ) ); //  79792266297612000
document.write( Math.bpow( 7, 20 ) ); // 79792266297612001

720 JavaScript  Math.pow BigInt使 Math.bpow 

bigint.js v0.4  bigint.js v0.5 

 (ver.0.4)


Bigint oo o


objBigint = new Bigint( arg )

arg JavaScript20 objBig:
objBig = new Bigint("1234567890 55555 00000")

Bigint.n( arg )

new使使Bigint.n(1) 1objBig 11
Bigint.add( objBig, Bigint.n(1) )
Bigint
Bigint.add( objBig, 1 )


objBigint.toString(radix)

radix 10 eval 10radix = 10 JavaScriptradix = 2 2JavaScript toString(2) .toString()  JavaScript BigintBigInt toString 210 radix 

objBigint.negative()

objBigintBigint

objBigint.sign()

調1-10objBigintBigint

objBigint.abs()

objBigintBigint

objBigint.getDigits()

10objBigintBigint

Bigint.cmp(o1, o2)

o1, o21-10o1, o2BigintBigintBigintBigint

Bigint.equal(o1, o2)

2 true false 

Bigint.add(o1, o2), Bigint.sub(o1, o2), Bigint.mul(o1, o2)

2

Bigint.div(o1, o2), Bigint.mod(o1, o2)

20o2

Bigint.divmod(o1, o2)

22

Bigint.pow(o1, o2)

o1o2

Bigint.powmod(o1, o2, o3)

o1o2o3Bigint.pow(o1, o2)mod powmod 使

Math.badd, Math.bsub, Math.bmul, Math.bdiv, Math.bmod, Math.bpow, etc.

JavaScriptMathBigintMathJavaScriptJavaScript +1 1 JavaScript b2float 使MathBigintBigint使


JavaScript

使


bigint_0_42212: 1

使bigint_0_4.js
<!-- ライブラリを呼び出す -->
<script type="text/javascript"
 src="http://m17n.cool.ne.jp/demo/bigint/bigint_0_4.js"></script>
<script type="text/javascript">
// 試したいコードを書く

var a = Math.pow( 2, 100 );
var b = Math.bpow( 2, 100 );
_debug( "2の100乗は、JavaScript自身によると、" + a );
_debug( "でも、正確な値は、" + b );

</script>

URL



https://yosei.fi/articles/5/25/#d20530


64-bit RSA by JavaScript

2002528
IDd20528


200264RSA 20041024 JavaScript: RSA20042


RSARSAJavaScriptPGP24-bitRSA24-bit64-bit

64RSAJavaScriptJavaScript24JavaSciript

RSARSA

253


JavaScript253 使JavaScript badd, bsub, bmul, bdiv, bpow 使

253 
9 00719 92547 40992
101664使
15864 09681 24704 1957017023 51553 19066 68755 ( mod 24552 16349 47175 97467 )
202020JavaScript2020
15864 09681 24704 19570  17023 51553 19066 68755


2使 Netscape 4.79 2 .toString(2) 253 232 110202 .toString(2) 
function radix2( arg ) {
    var N = new Array();
    if( isBigInt( arg ) ) N = bcopy( arg );
    else N = bset( arg.toString() );

    var f = b2float(N);
    var digit = Math.ceil( Math.log(f) / Math.log(2) );

    while(1) {
        var P = bset(digit-1);
        var test = b2float(      bdiv( N, bpow([2],P) )      );
        if( test >= 2 ) digit++;
        else if( test <1) digit--;
        else break;
    }

    var Power = new Array(digit);

    for( var i=0; i<=digit-1; i++ ) {
        if( i==0 ) Power[i] = [1];
        else Power[i] = bmul( Power[i-1] , [2] );
    }

    var R = bcopy(N);
    var ret = "";
    for( var power = digit-1; power >= 0; power-- ) {
        var X = Power[ power ];
        var Q = bdiv( R , X );

        if(b2float(Q)==1) {
            ret += "1";
            R = bsub( R, X );
        } else {
            ret += "0";
        }
    }
    return ret;
}

24×÷badd, bsub, bmul, bdiv, bmod 

IEMozillaNetscape

64




643222 Math.random() 使

246432101053 bdiv 

200210

6432

2641020RSA
 P = 52682 42677
 Q = 60009 18397
1
PQ = 31614 29440 02698 28769
i=3  i=5011050JavaScriptbmul( P, Q ) 1使


64RSA N = 20978 37388 62382 78843 , α = 48408 91627 使ppαNpα mod N 10N=120αN調NβRSA

β
β = 17231 12278 06360 67683
βNp


64128JavaScript25364JavaScript128256使

64


2PQNNPQ

i=2, 3, 5, 7,... N N N N 10210101010121210141016101020211





24RSA64RSA246424642464246410JavaScript

10100RSA

23102101001002



1002Windows 95 32MBWindows 2000 Linux

PC100100使


1


2002-05-28 Netscape 4JavaScriptJavaScript  n.toString(2)  n2Netscape 4 232 232
/0/0/0/0//000000/00000//000/0/0
'1' (0x31)  '0' (0x30)  '/' (0x2F) IEMozilla253  JavaScript 

リンク

この記事のURL







使

 


 <メールアドレス>