Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/436.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用素数分解查找数的最小公倍数(如何模拟素数表)_Javascript_Arrays_Algorithm - Fatal编程技术网

Javascript 使用素数分解查找数的最小公倍数(如何模拟素数表)

Javascript 使用素数分解查找数的最小公倍数(如何模拟素数表),javascript,arrays,algorithm,Javascript,Arrays,Algorithm,我处理这个问题的方法很可能有缺陷,但我已经接近完成解决方案了。给定数字2和10,我必须找到这两个数字的最小公倍数,加上它们范围内的数字。 (2,3,4,5,6,7,8,9,10) 我创建了一个函数,用于返回每个数字的素数因子,并将它们放入数组中。这就是我迷路的地方。我不知道如何减少/过滤掉过多的素数 我应该最终乘以2*2*2*3*3*5*7,但是过滤唯一的数字会得到2*3*5*7,或者如果我在数组展平之前过滤数字,则会得到2*3*2*5*2*3*7*2*3*5 function smallest

我处理这个问题的方法很可能有缺陷,但我已经接近完成解决方案了。给定数字2和10,我必须找到这两个数字的最小公倍数,加上它们范围内的数字。 (2,3,4,5,6,7,8,9,10)

我创建了一个函数,用于返回每个数字的素数因子,并将它们放入数组中。这就是我迷路的地方。我不知道如何减少/过滤掉过多的素数

我应该最终乘以2*2*2*3*3*5*7,但是过滤唯一的数字会得到2*3*5*7,或者如果我在数组展平之前过滤数字,则会得到2*3*2*5*2*3*7*2*3*5

function smallestCommons(arr) {
    // factorize a number function
    function factorization(num) {
        let primesArr = [];
        // i is what we will divide the number with
        for (let i = 2; i <= Math.sqrt(num); i++) {
            // if number is divisible by i (with no remainder)
            if (num % i === 0) {
                // begin while loop that lasts as long as num is divisible by i
                while (num % i === 0) {
                    // change the value of num to be it divided by i
                    num = num / i;
                    // push the prime number used to divide num
                    primesArr.push(i);
                }
            }
        }
        // if num is not the number 1 after the for loop
        // push num to the array because it is also a prime number
        if (num != 1) {
            primesArr.push(num);
        } 
        return primesArr;
    }
    // sort from lowest to highest
    arr.sort((a,b) => a - b);
    let range = [];
    let primeFacts = [];
    // push range of numbers to fullArr
    for (let i = arr[0]; i <= arr[1]; i++) {
        range.push(i);
    }
    console.log(range); // [2,3,4,5,6,7,8,9,10]
    // loop for iterating through range numbers
    for (let i = 0; i < range.length; i++) {
        // push the prime factors of each range number
        primeFacts.push(factorization(range[i]));
    }
    console.log(primeFacts); 
    // flatten the array, then return the product of numbers
    return primeFacts
                .reduce((newArray, arr) => newArray = [...newArray,...arr] ,[])
                .reduce((product, num) => product *= num); 
};

console.log(smallestCommons([2,10]));
我如何模拟它并将其添加到代码中?->

将此作为基本因子及其程度的表格:

    2  3  5  7
 2  1
 3     1
 4  2
 5        1
 6  2  2
 7           1
 8  3
 9     2
10  1     1
对于LCM,取每列中的最大度数:

    3  2  1  1
将这些力量相乘;这就是你的答案:

2^3 * 3^2 * 5^1 * 7^1
扩展

要获得GCD,请在每列中取最小的度数(包括0)。

您必须使用素数分解,还是只需要最低的公倍数?因为还有另一种更有效的算法,叫做欧几里德算法。你可以在这里阅读:

(注:通过欧几里德算法计算LCM需要GCD,但也有欧几里德算法)

现在,上面提到的算法适用于两个数字,但我认为(还没有从数学上验证它,所以你需要自己检查一下)你可以使用左归约

最终结果如下所示:

var getLCM = (a, b) => {
    // Implement Euclidean LCM algorithm here...
};

var getTotalLCM = (numbers) => {
    return numbers.reduce((totalLCM, next) => getLCM(totalLCM, next), 1);
}

var result = getTotalLCM([ 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
这里,
getTotalLCM
将计算1和2的LCM(1,因为这是我们传递给
reduce()
)的初始累加器值),当然是2。然后计算2和3的LCM,即6;然后是6和4,这是12,然后是12和5,这是60,然后是6和60,这仍然是60,依此类推。我想这就是你要找的

有关
reduce()
工作原理的详细信息,请参见:
我找到了解决方案。因子分解函数现在返回一个对象,而不是一对素数键-指数值。通过for in循环和reduce方法,输出LCM

function smallestCommons(arr) {
    // factorize a number function
    function factorization(num) {
        let primesObj = {};
        // i is what we will divide the number with
        for (let i = 2; i <= Math.sqrt(num); i++) {
            // if number is divisible by i (with no remainder)
            if (num % i === 0) {
                let exponent = 0;
                // begin while loop that lasts as long as num is divisible by i
                while (num % i === 0) {
                    // change the value of num to be it divided by i
                    num = num / i;
                    exponent++;
                    // create key value pair where exponent is the value
                    primesObj[i] = exponent;
                }
            }
        }
        // if num is not the number 1 after the for loop
        // push num to the array because it is also a prime number
        if (num != 1) {
            primesObj[num] = 1;
        } 
        return primesObj;
    }
    // sort from lowest to highest
    arr.sort((a,b) => a - b);
    let range = [];
    let primeFacts = [];
    // push range of numbers to fullArr
    for (let i = arr[0]; i <= arr[1]; i++) {
        range.push(i);
    }
    console.log(range); // [2,3,4,5,6,7,8,9,10]
    // loop for iterating through range numbers
    for (let i = 0; i < range.length; i++) {
        // push the prime factors of each range number
        primeFacts.push(factorization(range[i]));
    }
    console.log(primeFacts); 
    // create a filtered object with only the largest key value pairs
    let primeExponents = primeFacts.reduce((newObj,currObj)=> {
        for (let prime in currObj) {
            // create new key value pair when key value pair does not exist
            if (newObj[prime] === undefined) {
                newObj[prime] = currObj[prime];
            }
            // overwrite key value pair when current Object value is larger
            else if (newObj[prime] < currObj[prime]) {
                newObj[prime] = currObj[prime];
            }
        }
        return newObj;
    },{});
    let finalArr = [];
    // push appropriate amount of primes to arr according to exponent
    for (let prime in primeExponents) {
        for (let i = 1; i <= primeExponents[prime]; i++) {
            finalArr.push(parseInt([prime]));
        }
    }
    return finalArr.reduce((product, num) => product *= num);
};

console.log(smallestCommons([2,10]));
function smallestCommons(arr){
//分解一个数函数
函数分解(num){
设primesObj={};
//我就是我们要用它来除以这个数的
for(设i=2;i a-b);
让范围=[];
让primeFacts=[];
//将数字范围推到fullArr
for(设i=arr[0];i{
for(用currObj表示素数){
//当键值对不存在时创建新的键值对
if(newObj[prime]==未定义){
newObj[prime]=currObj[prime];
}
//当当前对象值较大时覆盖键值对
else if(newObj[prime]
要从素数分解到LCM,您需要计算每个素数的最大数量。因此,对于每个分解,我将创建一个素数到计数的映射。我将跟踪所需的每个因子的最大数量:

function lcm(primeFacts){
    var maxPrimes = {}; // stores the highest number of each prime factor required 
    for(var i = 0; i < primeFacts.length; i++){
        var map = {};
        var factors = primeFacts[i];
        for(var j = 0; j < factors.length; j++){
            // check to see whether the factor already exists in the map
            if(map[factors[j]]) map[factors[j]]++;
            else map[factors[j]] = 1;

            // check to make sure the max count exists
            if(!maxPrimes[factors[j]]) maxPrimes[factors[j]] = 1;
            if(maxPrimes[factors[j]] < map[factors[j]])
                maxPrimes[factors[j]] = map[factors[j]];
        }
    }

好的,我正试图找出如何将其实现到代码中。从您发布的代码开始,接下来的问题是设置、填充和遍历二维数组。当遇到SO级别的阻塞点时,请再次发布。我决定更改分解函数的返回值。它现在返回一个对象。然后我循环遍历该对象在值最大的地方只保留最大的唯一键。然后,我再次循环使用它来创建一个具有适当数量的素数的数组。最后,我将数组缩减为乘积。出色的矢量化…它有效吗?如果不行,我建议单独问一个问题来解决最后的位。
function lcm(primeFacts){
    var maxPrimes = {}; // stores the highest number of each prime factor required 
    for(var i = 0; i < primeFacts.length; i++){
        var map = {};
        var factors = primeFacts[i];
        for(var j = 0; j < factors.length; j++){
            // check to see whether the factor already exists in the map
            if(map[factors[j]]) map[factors[j]]++;
            else map[factors[j]] = 1;

            // check to make sure the max count exists
            if(!maxPrimes[factors[j]]) maxPrimes[factors[j]] = 1;
            if(maxPrimes[factors[j]] < map[factors[j]])
                maxPrimes[factors[j]] = map[factors[j]];
        }
    }
    var multiple = 1;
    for(var prime in maxPrimes){
        multiple *= prime ^ maxPrimes[prime];
    }
}