math-theory
Version:
Mathematical Theory 质数,最大公约数,最小公倍数,整除
556 lines (543 loc) • 19.9 kB
JavaScript
var theory = (function(){
Number.prototype.add = function(num){
return Math.round((this + num) * 1e12) / 1e12
}
Number.prototype.sub = function(num){
return Math.round((this - num) * 1e12) / 1e12
}
Number.prototype.mul = function(num){
return Math.round((this * num) * 1e12) / 1e12
}
Number.prototype.div = function(num){
return Math.round((this / num) * 1e12) / 1e12
}
String.prototype.replaceAt=function(index, character) {
return this.substr(0, index) + character.toString() + this.substr(index+character.toString().length);
}
var _gcd = function(a,b){
//两个数的最大公约数
b = b || 0
var temp;
if(parseInt(a) < parseInt(b)){
temp = a
a = b
b = temp
}
while(b != 0){
temp = a % b
a = b
b = temp
}
return a;
}
var _lcm = function(a,b){
//求两个数的最小公倍数
var temp
temp = a * b / _gcd(a,b); //最小公倍数等于两数之积除以最大公约数
return temp
}
var _rd = function(t1,t2,t3){//t1为下限,t2为上限,t3为需要保留的小数位
function isNum(n){
return /^\d+$/.test(n);
}
if(!t1 || (! isNum(t1)) ){t1=0;}
if(!t2 || (! isNum(t2)) ){t2=0;}
if(!t3 || (! isNum(t3)) ){t3=0;}
t3 = t3>15?15:t3; // 小数位不能大于15位
var ra = Math.random() * (t2 - t1) + t1
,du=Math.pow(10,t3)
,ra = Math.round(ra * du)
if(t3 !== 0){
//计算出不是10的倍数的数字,防止产生小数的时候末尾是0变成非小数,所以再加上一个1-9的随机数
var mr = ra % 10 === 0 ? (ra + parseInt(Math.random() *9 + 1)) : ra
}else{
var mr = ra
}
ra = mr / du;
return ra;
}
var _leastFactor = function(n){
if (isNaN(n) || !isFinite(n)) return NaN;
if (n==0) return 0;
if (n%1 || n*n<2) return 1;
if (n%2==0) return 2;
if (n%3==0) return 3;
if (n%5==0) return 5;
var m = Math.sqrt(n);
for (var i=7;i<=m;i+=30) {
if (n%i==0) return i;
if (n%(i+4)==0) return i+4;
if (n%(i+6)==0) return i+6;
if (n%(i+10)==0) return i+10;
if (n%(i+12)==0) return i+12;
if (n%(i+16)==0) return i+16;
if (n%(i+22)==0) return i+22;
if (n%(i+24)==0) return i+24;
}
return n;
}
var _permutations = function(n,k){
//排列
var result = 1, i,len = arguments.length
if(len === 1){
k = n
}
if(n < k){
throw new Error("n must bigger than k")
return
}
for(i=n;i>(n-k);i-=1){
result *= i
}
return result
}
return {
rd : _rd
,format2Latex : function(_str){
/*
* 将单个非latex格式的数字转换成latex格式
*/
var a = _str.toString()
var reg = /(\$\{.*?\}\$)/g
var latexArr = a.match(reg)
if(latexArr){
a = a.replace(reg,"###")
}
var geo = /(#{.+}#)/g
a = a.replace(geo,"~~~")
var geoStr = RegExp.$1
a = a.replace(/\d+/g,function(match, contents, offset, s){
var str = ''
return (str.substr(0,s) + "${" + match + "}$" + str.substr(s+match.toString().length))
});
var str = this.comma2Chinese(a)
if(geoStr){
str = str.replace("~~~",geoStr)
}
if(latexArr){
for(var i=0;i<latexArr.length;i+=1){
var temp = latexArr[i]
str = str.replace(/###/,temp)
}
}
return str
}
,comma2Chinese : function(_str){
return _str
.replace(/,/g,",")
.replace(/\?/g,"?")
.replace(/:/g,":")
.replace(/;/g,";")
}
,primeFactorization : function(num){
/*
* 将一个数分解质因数
* return array
* */
var root = Math.sqrt(num),
result = arguments[1] || [], //get unnamed paremeter from recursive calls
x = 2;
if(num % x){//if not divisible by 2
x = 3;//assign first odd
while((num % x) && ((x = x + 2) < root)){}//iterate odds
}
//if no factor found then num is prime
x = (x <= root) ? x : num;
result.push(x);//push latest prime factor
//if num isn't prime factor make recursive call
//arguments.callee 递归
return (x === num) ? result : arguments.callee(num/x, result) ;
}
,partNum : function(n){
/*
* 把一个多位数分割成单个数字,并按照从低到高反序排列返回一个数字
* return array
* */
var nArr = n.toString().split("")
,i,arr = []
for(i=0;i<nArr.length;i+=1){
arr.push(parseInt(nArr[i]))
}
return arr.reverse()
}
,getPrimes : function(_max,_min){
/*
* _max 最大范围值内的质数
* _min 最小范围,如果不传,则从1开始
* 获取一定范围内的质数
* return Array
* */
var max = _max
,min = _min || 2
var sieve = [], i, j, primes = [];
for (i = 2; i <= max; ++i) {
if (!sieve[i]) {
// i has not been marked -- it is prime
primes.push(i);
for (j = i << 1; j <= max; j += i) {
sieve[j] = true;
}
}
}
var result = []
for(i=0;i<primes.length;i+=1){
if(primes[i] >= min){
result.push(primes[i])
}
}
return result;
}
,checkRepeat : function(sArr,subArr){
/*
* 查找一个数组中截取某部分之后可能会出现的重复key值
* sArr 要查找的数字集合
* subStr 截取字符串的方式
* return object(非重复的)
* */
var i,same = {},diff = {},sameArr = []
for(i=0;i<sArr.length;i+=1){
var temp = sArr[i].toString(),key = ""
for(var j=0;j<subArr.length;j+=2){
key += temp.substring(subArr[j],subArr[j+1])
}
if(!same[key]){
if(diff[key]){
same[key] = temp
sameArr.push(temp)
sameArr.push(diff[key])
delete diff[key]
}else{
diff[key] = temp
}
}else{
sameArr.push(temp)
}
}
//返回唯一答案的结果集
return diff
}
,diffMedian : function(_digit,_min,_max){
/*
* _digit 生成几位数
* _min 从哪里开始
* _max 到哪里结束
* */
var digit = (_digit>1 && _digit<=9) ? _digit : 2
,min = _min || 0
,max = _max || 9
,arr = [], i,result = ""
if((max - min + 1) < digit){
throw new Error("there is not enough number")
}
for(i=min;i<=max;i+=1){
arr.push(i)
}
if(min === 0){
var frd = _rd(1,9)
}else{
var frd = _rd(0,arr.length-1)
}
result += arr.splice(frd,1)[0]
for(i=1;i<digit;i+=1){
result += arr.splice(_rd(0,arr.length-1),1)
}
return parseInt(result)
}
,ngcd : function(_array){
/*
* 接收一个数组
* 返回这个数组内的最大公约数
* return int
* */
if(_array.length === 1){
return _array[0]
}
var x = _array.splice(_array.length-1,1)[0]
//arguments.callee 递归
return _gcd(x,arguments.callee(_array))
}
,nlcm : function(_array){
/*
* 接收一个数组
* 返回这个数组内的最小公倍数
* return int
* */
if(_array.length === 1){
return _array[0]
}
var x = _array.splice(_array.length-1,1)[0]
//arguments.callee 递归
return _lcm(x,arguments.callee(_array))
}
,isPrime : function(number){
if (isNaN(number) || !isFinite(number) || number % 1 || number < 2) return false;
if (number == _leastFactor(number)) return true;
return false;
}
,toFactorPowerList : function(factors) {
/*
* factors Array
* 数组中有重复项,然后转换成次幂关系,
* return [[],[]]
* */
factors.sort()
var result = [];
var factor = factors[0];
var count = 1;
for (var i = 1; i < factors.length; i++) {
if (factors[i] == factor) {
count++;
} else {
result.push([factor, count]);
factor = factors[i];
count = 1;
}
}
result.push([factor, count]);
result.sort(function(a,b){
return a[0] - b[0]
})
return result;
}
,permutator : function(input) {
/*
* input Array [1,2,3]
* 数组内元素的排列问题,阶乘
* return [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
* */
var set =[];
function permute (arr, data) {
var cur, memo = data || [];
for (var i = 0; i < arr.length; i++) {
cur = arr.splice(i, 1)[0];
if (arr.length === 0) set.push(memo.concat([cur]));
permute(arr.slice(), memo.concat([cur]));
arr.splice(i, 0, cur);
}
return set;
}
return permute(input);
}
,getCommonDivisor : function(num){
/*
* 求一个数的约数
* return array
* */
var arr = [];
arr.push(1);
for (var i=2; i<=num/2; i++) {
if(num % i == 0){
arr.push(i);
}
}
//最后该数本身也要加入到数组去
arr.push(num);
return arr;
}
,float2rat : function (x) {
/*
* 直接将小数转化为分数
* x = 2.5 return 5/2 string
* x = 2 return 2 int
*
* */
var tolerance = 1.0E-6;
var h1=1; var h2=0;
var k1=0; var k2=1;
var b = x;
do {
var a = Math.floor(b);
var aux = h1; h1 = a*h1+h2; h2 = aux;
aux = k1; k1 = a*k1+k2; k2 = aux;
b = 1/(b-a);
} while (Math.abs(x-h1/k1) > x*tolerance);
if(k1 === 1){
return h1
}
return h1+"/"+k1;
}
,getSimpleFraction:function(a, b , mix) {// a/b
/*
* 化简分数
* a:分子
* b:分母
* mix:true带分数,false假分数,默认false
*
*/
var tempA = a, tempB = b;
var result = [tempA, tempB ];
if (b % a == 0) {
result = [1, b / a ];
}
for (var i = 2; i < tempA; i++) {
if (tempA % i == 0 && tempB % i == 0) {
tempA = tempA / i;
tempB = tempB / i;
result = arguments.callee(tempA, tempB);
break;
}
}
if(mix==true){
result = [result[0]/result[1],result[0]%result[1],result[1]];
}
return result;
}
,str2Fraction:function(frac){
/*
* 将带分数或假分数的字符串形式转换成假分数
* frac:分数字符串
* return:[分子,分母]
*/
var r = frac.match(/(\d+) +(\d+)\/(\d+)/);
if(r==null){
r = frac.match(/(\d+)\/(\d+)/);
}
if(r==null){
return frac
}
var a = parseInt(r[r.length-2]);
var b = parseInt(r[r.length-1]);
if(r.length == 4){
a += parseInt(r[1])*b;
}
return [a,b];
}
,linearXY : function(a,b,c,d,e,f){
//二元一次方程
//return [1,3,4,2] 1/3 4/2
var result = [];
// 消元法得出
var yUp = (c * d - a * f);
var yDown = (b * d - a * e);
var xUp = c * yDown - b * yUp;
var xDown = a * yDown;
result[0] = xUp;
result[1] = xDown;
result[2] = yUp;
result[3] = yDown;
return result
}
,productTwoDimensionalArray:function(count,a,first){
/*
* 分数列项
* count 长度 5
* a 递进 2
* first 起始位置 2
* return [[2,4],[4,6],[6,8],[8,10],[10,12]]
*
* */
var results = [];
for (var i = 0; i < count; i++) {
results[i] = [];
for (var j = 0; j < 2; j++) {
results[i][j] = i * a + j * a + first;
}
}
return results;
}
,weekdaytoChinese : function(weekday){
/*
* weekday是1-7之间的数字
* return 是1到7对应的星期的中文,但是7对应的是日
* */
var weekdayInChinese,week = weekday % 7;
switch (week.toString()){
case "0":
weekdayInChinese = "星期日";
break;
case "1":
weekdayInChinese = "星期一";
break;
case "2":
weekdayInChinese = "星期二";
break;
case "3":
weekdayInChinese = "星期三"
break;
case "4":
weekdayInChinese = "星期四";
break;
case "5":
weekdayInChinese = "星期五";
break;
case "6":
weekdayInChinese = "星期六";
break;
default:
weekdayInChinese = "星期日";
break;
}
return weekdayInChinese;
}
,yearIsOrNotLeapYear:function(yearNumber){
/*
* yearNumber 年份
* return 是否是闰年 0 or 1
*
* */
var isOrNotLeapYear,yearDescription;
if(yearNumber % 4 == 0 && yearNumber % 400 != 0)
{
yearDescription = "闰年";
isOrNotLeapYear = 1;
}
else
{
yearDescription = "平年";
isOrNotLeapYear = 0;
}
return isOrNotLeapYear;
}
,num2Chinese : function(_num){
var arr = ["零","一","二","三","四","五","六","七","八","九","十"]
return arr[_num] || _num
}
,pointPos : function(x1,y1,x2,y2,n){
/*
* 矢量与定比分点、中点公式AP:PB=n
* A(x1,y1)点坐标
* B(x2,y2)点坐标
* AP:PB = n
* */
return {x:(x1+n*x2)/(1+n),y:(y1+n*y2)/(1+n)}
}
,permutations : _permutations//排列
,combinations : function(n,k){
/*
* C n 取 k
* return int
*
* */
var len = arguments.length
if(len === 1){
k = n
}
if(n < k){
throw new Error("n must bigger than k")
return
}
var np = _permutations(n,k),kp = _permutations(k)
return np.div(kp)
}
,factorialProcess : function(n,k){
/*
* 阶乘的中是哪几个数相乘
* return arr
*
* */
var arr = new Array(),len = arguments.length,i
if(len === 1){
k = n
}
if(n < k){
throw new Error("n must bigger than k")
return
}
for(i=n;i>(n-k);i-=1){
arr.push(i)
}
return arr
}
}
})
module.exports = theory()