      1 ﻿
      2 /**
      3  * @name	CeL function for math
      4  * @fileoverview
      5  * 本檔案包含了數學演算相關的 functions。
      6  * @since
      7  */
      8
      9 /*
     10 TODO:
     11 大數計算
     12 方程式圖形顯示 by SVG
     13 */
     14
     15
     16
     17 if (typeof CeL === 'function')
     18 CeL.setup_module('data.math',
     19 {
     20 require : 'data.split_String_to_Object',
     21 code : function(library_namespace, load_arguments) {
     22
     23 //	requiring
     24 var split_String_to_Object;
     25 eval(library_namespace.use_function(this));
     26
     27
     28
     29 /**
     30  * null module constructor
     31  * @class	數學相關的 functions
     32  */
     33 CeL.data.math
     34 = function() {
     35 	//	null module constructor
     36 };
     37
     38 /**
     39  * for JSDT: 有 prototype 才會將之當作 Class
     40  */
     41 CeL.data.math
     42 .prototype = {
     43 };
     44
     45
     46
     47
     48
     49 /*
     50 	Math	---------------------------------------------------------------
     51 */
     52
     53 /*
     54 //{var v=Math.LN2,d=mutual_division(v),q=to_rational_number(v);alert('值	'+v+'\n序列	'+d+'\n近似值	'+q[0]+' / '+q[1]+'\n約	'+(q=q[0]/q[1])+'\n值-近似	'+(q-=v)+'\n差'+(Math.abs(q=10000*q/v)>1?'萬分之'+q.to_fixed(2)+' ( '+q+' / 10000 )':'億分之'+(q*=10000).to_fixed(2)+' ( '+q+' / 100000000 )'),0,'近似值	'+v);}
     55
     56 //{var d=new Date,a=.142857,b=1000000,i=0,c;for(i=0;i<10000;i++)c=mutual_division(a);alert(c+'\n'+gDate(new Date-d));}
     57 */
     58
     59 CeL.data.math
     60 .
     61 /**
     62  * 輾轉相除 n1/n2 或 小數 n1/1 轉成 整數/整數
     63  * @param {Number} n1	number 1
     64  * @param {Number} [n2]	number 2
     65  * @param {Number} times	max 次數, 1,2,..
     66  * @return	{Array}	連分數序列 ** 負數視 _.mutual_division.done 而定!
     67  */
     68 mutual_division = function mutual_division(n1, n2, times) {
     69 	var q = [], c;
     70 	if (isNaN(times) || times <= 0)
     71 		times = 80;
     72 	if (!n2 || isNaN(n2))
     73 		n2 = 1;
     74
     75 	if (n1 != Math.floor(n1)) {
     76 		c = n1;
     77 		var i = 9, f = n2;
     78 		while (i--)
     79 			//	以整數運算比較快！這樣會造成整數多4%，浮點數多1/3倍的時間，但仍值得。
     80 			if (f *= 10, c *= 10, c === Math.floor(c)) {
     81 				n1 = c, n2 = f;
     82 				break;
     83 			}
     84 	}
     85
     86 	//	連分數負數之處理。更沒問題的: (n1 < 0?1:0) ^ (n2 < 0?1:0)
     87 	if (_.mutual_division.mode && ((n1 < 0) ^ (n2 < 0))) {
     88 		// 使兩數皆為正
     89 		if (n2 < 0)
     90 			n2 = -n2;
     91 		else
     92 			n1 = -n1;
     93
     94 		q.push(-(1 + (n1 - (c = n1 % n2)) / n2));
     95 		n1 = n2, n2 -= c;
     96 	}
     97
     98 	/* old:
     99 	 while(b&&n--)
    100 	  d.push((a-(c=a%b))/b),a=b,b=c;	//	2.08s@10000	可能因為少設定（=）一次c所以較快。但（若輸入不為整數）不確保d為整數？用Math.floor((a-(c=a%b))/b)可確保，速度與下式一樣快。
    101 	  //d.push(c=Math.floor(a/b)),c=a-b*c,a=b,b=c;	//	2.14s@10000:mutual_division(.142857)
    102 	  //d.push(Math.floor(a/b)),b=a%(c=b),a=c;	//	2.2s@10000
    103 	 //if(n)d.push(0);
    104 	*/
    105
    106 	//	2.4s@10000	可能因為少設定（=）一次c所以較快。但（若輸入不為整數）不確保d為整數？用Math.floor((a-(c=a%b))/b)可確保，速度與下式一樣快。
    107 	while (times--)
    108 		if (n2)
    109 			q.push((n1 - (c = n1 % n2)) / n2), n1 = n2, n2 = c;
    110 		else {
    111 			//	[ .. , done mark, (最後非零的餘數。若原 n1, n2 皆為整數，則此值為 GCD。但請注意:這邊是已經經過前面為了以整數運算，增加倍率過的數值!!) ]
    112 			q.push(_.mutual_division.done, n1);
    113 			//library_namespace.debug('done: ' + q);
    114 			break;
    115 		}
    116
    117 	//	2.26s@10000
    118 	//while(b&&n--)if(d.push((a-(c=a%b))/b),a=b,!(b=c)){d.push(0);break;}
    119
    120 	//var m=1;c=1;while(m&&n--)d.push(m=++c%2?b?(a-(a%=b))/b:0:a?(b-(b%=a))/a:0);//bug
    121
    122 	return q;
    123 };
    124 CeL.data.math
    125 .
    126 mutual_division.done = -7;//''
    127
    128 CeL.data.math
    129 .
    130 /**
    131  * !!mode:連分數處理，對負數僅有最初一數為負。
    132  */
    133 mutual_division.mode = 0;
    134
    135 CeL.data.math
    136 .
    137 /**
    138  * 取得連分數序列的數值
    139  * @param {Array} sequence	序列
    140  * @param {Number} [max_no]	取至第 max_no 個
    141  * @requires	mutual_division.done
    142  * @return
    143  * @see
    144  * var a=continued_fraction([1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]);
    145  * alert(a+'\n'+a[0]/a[1]+'\n'+Math.SQRT2+'\n'+(Math.SQRT2-a[0]/a[1])+'\n'+mutual_division(a[0],a[1]));
    146  */
    147 continued_fraction = function(sequence, max_no) {
    148 	if (!library_namespace.is_Array(sequence) || !sequence.length)
    149 		return sequence;
    150
    151 	if (sequence[sequence.length - 2] === _.mutual_division.done)
    152 		sequence.length -= 2;
    153
    154 	if (sequence.length < 1)
    155 		return sequence;
    156
    157 	if (!max_no/* ||max_no<2 */|| max_no > sequence.length)
    158 		max_no = sequence.length;
    159
    160 	var a, b;
    161 	if (max_no % 2)
    162 		b = 1, a = 0;
    163 	else
    164 		a = 1, b = 0;
    165 	//sequence[max_no++]=1;if(--max_no%2)b=sequence[max_no],a=s[--max_no];else a=sequence[max_no],b=sequence[--max_no];
    166
    167 	//library_namespace.debug('a=' + a + ', b=' + b + ', max_no=' + max_no);
    168 	while (max_no--)
    169 		if (max_no % 2)
    170 			b += a * sequence[max_no];
    171 		else
    172 			a += b * sequence[max_no];
    173 	//library_namespace.debug('a=' + a + ', b=' + b);
    174 	return [ a, b ];
    175 };
    176
    177
    178 CeL.data.math
    179 .
    180 /**
    181  * The best rational approximation. 取得值最接近之有理數 (use 連分數 continued fraction), 取近似值.
    182  * c.f., 調日法
    183  * 在分子或分母小於下一個漸進分數的分數中，其值是最接近精確值的近似值。
    184  * @example
    185  * to_rational_number(4088/783)
    186  * @param {Number} number	number
    187  * @param {Number} [rate]	比例在 rate 以上
    188  * @param {Number} [max_no]	最多取至序列第 max_no 個
    189  * 					TODO : 並小於 l: limit
    190  * @return	[分子, 分母, 誤差]
    191  * @requires	mutual_division,continued_fraction
    192  * @see
    193  * http://en.wikipedia.org/wiki/Continued_fraction#Best_to_rational_numbers
    194  */
    195 to_rational_number = function(number, rate, max_no) {
    196 	if (!rate)
    197 		//	This is a magic number: 我們無法準確得知其界限為何。
    198 		rate = 65536;
    199 	var d = _.mutual_division(number, 1, max_no && max_no > 0 ? max_no : 20),
    200 	i = 0, a, b = d[0], done = _.mutual_division.done;
    201
    202 	if (!b)
    203 		b = d[++i];
    204 	while (++i < d.length && (a = d[i]) !== done)
    205 		if (a / b < rate)
    206 			b = a;
    207 		else
    208 			break;
    209
    210 	if(0)
    211 		library_namespace.debug(
    212 			number + ' ' +
    213 			//	連分數表示
    214 			(d.length > 1 && d[d.length - 2] === _.mutual_division.done ?
    215 				'=' + ' [<em>' + d[0] + ';' + d.slice(1, i).join(', ') + '</em>'
    216 					+ (i < d.length - 2 ? ', ' + d.slice(i, -2).join(', ') : '')
    217 					+ '] .. ' + d.slice(-1) :
    218 				//	約等於的符號是≈或≒，不等於的符號是≠。
    219 				//	http://zh.wikipedia.org/wiki/%E7%AD%89%E4%BA%8E
    220 				'≈' + ' [<em>' + d[0] + ';' + d.slice(1, i).join(', ') + '</em>'
    221 					+ (i < d.length ? ', ' + d.slice(i).join(', ') : '') + ']: '
    222 					+ d.length + ',' + i + ',' + d[i]
    223 			)
    224 		);
    225 	d = _.continued_fraction(d, i);
    226 	//library_namespace.debug('→ ' + d[0] + '/' + d[1]);
    227 	if (d[1] < 0)
    228 		d[0] = -d[0], d[1] = -d[1];
    229
    230 	return [ d[0], d[1], d[0] / d[1] - number ];
    231 };
    232
    233
    234 /*	最大公因數/公約數	 Greatest Common Divisor
    235
    236 usage:
    237 	gcd(6,9)
    238 	GCD([5,3,8,2,6,9])
    239 */
    240 //_gcd[generateCode.dLK]='mutual_division,mutual_division_done';
    241 function _gcd(a,b){
    242  if(isNaN(a)||isNaN(b))
    243   return isNaN(b)?a:b;
    244
    245  var d=_.mutual_division(a,b);
    246  a=d.pop();
    247  if(d.pop()===_.mutual_division.done)
    248   return a;
    249 }
    250
    251 CeL.data.math
    252 .
    253 /**
    254  * Get GCD of 2 numbers
    255  * @param n1	number 1
    256  * @param n2	number 2
    257  * @return	GCD of the 2 numbers
    258  */
    259 gcd = function(n1, n2) {
    260 	/*
    261 	if (isNaN(a))
    262 		return b;
    263 	*/
    264 	//	必要!
    265 	if (!n2 || isNaN(n2))
    266 		return n1;
    267
    268 	//	也可最後再 Math.abs
    269 	/*
    270 	if (a < 0)
    271 		a = -a;
    272 	if (b < 0)
    273 		b = -b;
    274 	*/
    275
    276 	//	Euclidean algorithm
    277 	var r;
    278 	while (r = n1 % n2)
    279 		n1 = n2, n2 = r;
    280 	return n2 < 0 ? -n2 : n2;
    281 };
    282
    283 //GCD[generateCode.dLK]='gcd';
    284 function GCD(numA){
    285  var i=1,g=numA[0];
    286  for(;i<numA.length;i++)
    287   if(!isNaN(numA[i]))
    288    g=gcd(g,numA[i]);
    289  return g;
    290 }
    291 /*	最小公倍數	 Least Common Multiple
    292
    293 usage:
    294 	lcm(6,9)
    295 	lcm([5,3,8,2,6,9])
    296
    297 TODO:
    298 更快的方法：
    299 短除法
    300 一次算出 GCD, LCM
    301 */
    302 //lcm[generateCode.dLK]='gcd';
    303 function lcm(a,b){
    304  var l,g,i=1;
    305  if( typeof a=='object' && !isNaN(l=a[0]) ){
    306   while(i<a.length)
    307    l=lcm(l,a[i++]);
    308   return l;
    309  }
    310
    311  if( (g=gcd(a,b)) && !isNaN(g) )
    312   return a/g*b;
    313 }
    314
    315
    316 /*
    317 http://www.math.umbc.edu/~campbell/NumbThy/Class/Programming/JavaScript.html
    318 http://aoki2.si.gunma-u.ac.jp/JavaScript/
    319 */
    320
    321 CeL.data.math
    322 .
    323 /**
    324  * 得到平方數，相當於 Math.floor(Math.sqrt(number)).
    325  * get integer square root
    326  * @param {Number} positive number
    327  * @return	r, r^2 <= number < (r+1)^2
    328  * @example
    329  * var p = 20374345, q = CeL.math.floor_sqrt(p = p * p - 1); CeL.log(q + '<br/>' + (q * q) + '<br/>' + p + '<br/>' + (++q * q));
    330  * @see
    331  * <a href="http://www.azillionmonkeys.com/qed/sqroot.html" accessdate="2010/3/11 18:37">Paul Hsieh's Square Root page</a>
    332  * <a href="http://www.embeddedrelated.com/usenet/embedded/show/114789-1.php" accessdate="2010/3/11 18:34">Suitable Integer Square Root Algorithm for 32-64-Bit Integers on Inexpensive Microcontroller? | Comp.Arch.Embedded | EmbeddedRelated.com</a>
    333  */
    334 floor_sqrt = function(number){
    335 	if (isNaN(number = Math.floor(number)))
    336 		return;
    337 	var g = 0, v, h, t;
    338 	while ((t = g << 1) < (v = number - g * g)) {
    339 		//library_namespace.debug(t + ', ' + v);
    340 		h = 1;
    341 		while (h * (h + t) <= v)
    342 			// 因為型別轉關係，還是保留 << 而不用 *2
    343 			h <<= 1;//h *= 2;
    344 		g += h >> 1;//h / 2;//
    345 	}
    346 	//library_namespace.debug('end: ' + t + ', ' + v);
    347 	return g;
    348 };
    349
    350
    351 CeL.data.math
    352 .
    353 /**
    354  * 取得某數的質因數，因式分解/素因子分解, factorization, get floor factor.
    355  * 唯一分解定理(The Unique Factorization Theorem)告訴我們素因子分解是唯一的，這即是稱為算術基本定理 (The Fundamental Theorem of Arithmeric) 的數學金科玉律。
    356  * @param {Number} number
    357  * @return	{Array} [prime1,power1,prime2,power2,..]
    358  * @see
    359  * <a href="http://homepage2.nifty.com/m_kamada/math/10001.htm" accessdate="2010/3/11 18:7">Factorizations of 100...001</a>
    360  * @requires	floor_sqrt
    361  */
    362 factorization = function(number) {
    363 	var f = 2, p, a, l, r = [];
    364 	if (isNaN(number) || number < 1 || number >
    365 			/*
    366 			 * javascript 可以表示的最大整數值
    367 			 * 10^21-2^16-1 = 999999999999999934463
    368 			 * @see
    369 			 * http://www.highdots.com/forums/javascript/how-js-numbers-represented-internally-166538-4.html
    370 			 */
    371 			999999999999999934469)
    372 		return;
    373 	number = Math.floor(number);
    374
    375 	// 2,3
    376 	while (number > 1) {
    377 		if (number % f === 0) {
    378 			p = 0;
    379 			do
    380 				number /= f, p++;
    381 			while (number % f === 0); // do{n/=f,p++;}while(n%f==0);
    382 			r.push(f, p);
    383 		}
    384 		if (++f > 3)
    385 			break;
    386 	}
    387
    388 	a = 4, f = 5, l = _.floor_sqrt(number); // 5-初始化
    389 	while (number > 1) {
    390 		if (f > l) {
    391 			r.push(number, 1);
    392 			break;
    393 		}
    394 		// document.write('<br/>'+f+','+n);
    395 		if (number % f === 0) {
    396 			p = 0;
    397 			do {
    398 				number /= f, p++;
    399 			} while (number % f === 0);
    400 			l = _.floor_sqrt(number), r.push(f, p);
    401 		}
    402 		f += a = a === 2 ? 4 : 2;
    403 	}
    404 	return r;
    405 };
    406
    407 /*	test
    408 function count(n){
    409 var a=factorization(n),s='',v=1;
    410 if(a){
    411  for(var i=0;i<a.length;i+=2){s+='*'+a[i]+(a[i+1]>1?'^'+a[i+1]:'');v*=Math.pow(a[i],a[i+1]);}
    412  s=s.substr(1)+'='+v+'='+n;
    413 }else s='error! '+n;
    414 document.getElementById('result').value+=s+'\n-------------------------------------------\n';
    415 }
    416 */
    417
    418
    419 /*	猜測一個數可能的次方數。	2005/2/18 19:20未完成
    420 	type=0:整數,1:有理數
    421 	return [base分子,base分母,exponent分子,exponent分母]
    422 */
    423 function to_exponent(num,type){
    424  var bn,bd,en=1,ed,sq=[1,num],t,q,error=1e-9,g=function(n){q=_.to_rational_number(n,99999);if((!type||q[1]==1)&&!(q[0]>99999&&q[1]>99999)&&q[2]/n<error)bn=q[0],bd=q[1],ed=t;};//error:誤差
    425
    426  if(!ed)g(sq[t=1]);
    427  if(!ed)g(sq[t=2]=sq[1]*sq[1]);
    428  if(!ed)g(sq[t=3]=sq[1]*sq[2]);
    429  if(!ed)g(sq[t=4]=sq[2]*sq[2]);
    430  if(!ed)g(sq[t=5]=sq[2]*sq[3]);
    431  if(!ed)bn=num,bd=ed=1;
    432
    433  return [bn,bd,en,ed];
    434 }
    435 //var t=to_exponent(Math.pow(2/3,1/1));alert(t[0]+'/'+t[1]+'^'+t[2]+'/'+t[3]);
    436
    437
    438
    439
    440 /*
    441 for 出題
    442
    443 runCode.setR=0;
    444 for(var i=0,j,t,s,n_e;i<10;){
    445  t=2000+8000*Math.random();
    446  s=get_random_prime.get_different_number_set(3,t,t/8);
    447  if(s.LCM>9999)continue;
    448  n_e=[];
    449  n_e[s.GCD]=1;
    450  for(j=0;j<s.length;j++)
    451   if(n_e[s[j]])continue;
    452   else n_e[s[j]]=1;
    453  sl([s.GCD,s.LCM]+'<b style="color:#c4a">;</b> '+s);i++;
    454 }
    455
    456 */
    457
    458 //	求乘積
    459 function get_product(nums,till){	//	num array, 乘到比till小就回傳
    460  var p=1,i=0,l=nums.length;
    461  for(;i<l;i++){
    462   if(till&&p*nums[i]>till)break;
    463   p*=nums[i];
    464  }
    465  return p;
    466 }
    467
    468
    469 //	2009/10/21 11:57:47
    470 //get_random_prime[generateCode.dLK]='get_product';
    471 get_random_prime.primes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
    472 function get_random_prime(count,exclude,all_different){	//	個數, 排除
    473  var _f=arguments.callee,i,j,p=[],l;
    474  if(!count||count<1)count=1;
    475  if(!_f.excluded)
    476   _f.excluded=[];
    477  if(exclude)exclude=[];
    478
    479  for(j=0;j<count;j++){
    480   l=80;	//	timeout
    481   do{
    482    i=Math.round(10*Math.tan(Math.random()*1.5));
    483    if(!--l)return;	//	timeout
    484   }while(_f.excluded[i]);
    485   p.push(_f.primes[i]);
    486   if(exclude)exclude.push(i);
    487  }
    488
    489  //	選完才排除本次選的
    490  if(exclude)
    491   for(j=0,l=exclude.length;j<l;j++){
    492    i=exclude[j];
    493    if(_f.excluded[i])_f.excluded[i]++;
    494    else _f.excluded[i]=1;
    495   }
    496
    497  return count==1?p[0]:p;
    498 }
    499
    500 //	return [GCD, n1, n2, ..]
    501 get_random_prime.get_different_number_set=function(count,till,GCD_till){
    502  delete this.excluded;
    503  if(!GCD_till)GCD_till=1e5;
    504  if(!till)till=1e5;
    505
    506  var GCD=get_product(this(20,1),GCD_till),na=[],n_e=[],n,i=0,out;
    507  n_e[GCD]=1;
    508
    509  for(;i<count;i++){
    510   out=80;	//	timeout
    511   do{
    512    n=this(20);
    513    n.unshift(GCD);
    514    n=get_product(n,till);
    515   }while(n_e[n]&&--out);
    516   n_e[n]=1;
    517   na.push(n);
    518  }
    519
    520  if(typeof lcm=='function')
    521   na.LCM=lcm(na);
    522  na.GCD=GCD;
    523  return na;
    524 };
    525
    526
    527
    528 CeL.data.math
    529 .
    530 /**
    531  * VBScript has a Hex() function but JScript does not.
    532  * @param {Number} number
    533  * @return	{String} number in hex
    534  * @example
    535  * alert('0x'+CeL.hex(16725))
    536  */
    537 hex = function(number) {
    538 	return (number < 0 ? number + 0x100000000 : number - 0).toString(16);
    539 }
    540
    541 CeL.data.math
    542 .
    543 /**
    544  * 補數計算。
    545  * 正數的補數即為自身。若要求得互補之後的數字，請設成負數。
    546  * @param {Number} number
    547  * @return	{Number} base	1: 1's Complement, 2: 2's Complement, (TODO: 3, 4, ..)
    548  * @example
    549  * alert(complement())
    550  * @see
    551  * http://www.tomzap.com/notes/DigitalSystemsEngEE316/1sAnd2sComplement.pdf
    552  * http://en.wikipedia.org/wiki/Method_of_complements
    553  * http://en.wikipedia.org/wiki/Signed_number_representations
    554  * @since	2010/3/12 23:47:52
    555  */
    556 complement = function() {
    557 	return this.from.apply(this, arguments);
    558 };
    559
    560 _.complement.prototype = {
    561
    562 base : 2,
    563
    564 //	1,2,..
    565 bits : 8,
    566
    567 //	radix complement or diminished radix complement.
    568 //	http://en.wikipedia.org/wiki/Method_of_complements
    569 diminished : 0,
    570
    571 /**
    572  * 正負符號.
    573  * 正: 0/false,
    574  * 負 negative value:!=0 / true
    575  */
    576 sign : 0,
    577
    578 //	get the value
    579 valueOf : function() {
    580 	return this.sign ? -this.value : this.value;
    581 },
    582
    583 /**
    584  * set value
    585  */
    586 set : function(value) {
    587 	var m = Number(value), a = Math.abs(m);
    588 	if (isNaN(m) || m && a < 1e-8 || a > 1e12){
    589 		library_namespace.debug('complement.set: error number: ' + value);
    590 		return;
    591 	}
    592
    593 	this.sign = m < 0;
    594 	// this.value 僅有正值
    595 	this.value = a;
    596
    597 	return this;
    598 },
    599
    600
    601 /**
    602  * input
    603  */
    604 from : function(number, base, diminished) {
    605 	//	正規化
    606 	number = ('' + (number||0)).replace(/\s+$|^[\s0]+/g, '') || '0';
    607 	//library_namespace.debug(number + ':' + number.length + ',' + this.bits);
    608
    609 	//	整數部分位數
    610 	var value = number.indexOf('.'), tmp;
    611 	if (value == -1)
    612 		value = number.length;
    613 	//	TODO: not good
    614 	if (value > this.bits)
    615 		//throw 'overflow';
    616 		library_namespace.err('complement.from: overflow: ' + value);
    617
    618 	if (typeof diminished === 'undefined')
    619 		//	illegal setup
    620 		diminished = this.diminished;
    621 	else
    622 		this.diminished = diminished;
    623
    624 	if ((base = Math.floor(base)) && base > 0){
    625 		if (base === 1)
    626 			base = 2, this.diminished = 1;
    627 		this.base = base;
    628 	}else
    629 		//	illegal base
    630 		base = this.base;
    631 	//library_namespace.debug(base + "'s Complement");
    632
    633 	//	TODO: 僅對 integer 有效
    634 	value = parseInt(number, base);
    635 	tmp = Math.pow(base, this.bits - 1);
    636 	if (value >= tmp * base)
    637 		//throw 'overflow';
    638 		library_namespace.err('complement.from: overflow: ' + value);
    639
    640 	//library_namespace.debug('compare ' + value + ',' + tmp);
    641 	if (value < tmp)
    642 		this.sign = 0;
    643 	else
    644 		//library_namespace.debug('負數 ' + (tmp * base - (diminished ? 1 : 0)) + '-'+ value+'='+(tmp * base - (diminished ? 1 : 0) - value)),
    645 		this.sign = 1,
    646 		value = tmp * base - (diminished ? 1 : 0) - value;
    647
    648 	this.value = value;
    649 	//library_namespace.debug(number + ' → '+this.valueOf());
    650
    651 	return this;
    652 },
    653
    654 /**
    655  * output
    656  */
    657 to : function(base, diminished) {
    658 	if (!(base = Math.floor(base)) || base < 1)
    659 		base = this.base;
    660 	else if (base === 1)
    661 		base = 2, diminished = 1;
    662 	if (typeof diminished === 'undefined')
    663 		diminished = this.diminished;
    664
    665 	var value = this.value, tmp = Math.pow(base, this.bits - 1);
    666 	if (value > tmp || value === tmp && (diminished || !this.sign))
    667 		//throw 'overflow';
    668 		library_namespace.err('complement.to: overflow: ' + (this.sign ? '-' : '+') + value);
    669
    670 	if (this.sign){
    671 		tmp *= base;
    672 		if (diminished)
    673 			//	TODO: 僅對 integer 有效
    674 			tmp--;
    675 		//library_namespace.debug('負數 ' + value + '，sum=' + tmp);
    676 		// 負數，添上兩補數之和
    677 		value = tmp - value;
    678 	}
    679
    680 	//library_namespace.debug('value: ' + (this.sign ? '-' : '+') + value);
    681
    682 	value = value.toString(Math.max(2, this.base));
    683
    684 	return value;
    685 }
    686
    687 };
    688
    689 _.complement.prototype.toString = _.complement.prototype.to;
    690
    691
    692 /*
    693 	↑Math	---------------------------------------------------------------
    694 */
    695
    696
    697
    698
    699 return (
    700 	CeL.data.math
    701 );
    702 }
    703
    704
    705 });
    706
    707