找到一系列数字的最低公倍数

时间:2015-07-01 17:24:33

标签: javascript

我正在进行javascript任务,并且在理解代码时遇到了一些麻烦。我正在使用这个代码,它可以工作,但我想进一步分解它,以真正了解正在发生的事情。我已经对我理解的部分进行了评论,但是对于我来说,我已经对一些较为困难的部分提出了问题。



//Finding the Least Common Denominator with a Recursive Euclidean Algorithm 
//GCD = Biggest Number that is divides into both evenly
function gcd(a, b) {
  return b ? gcd(b, a % b) : Math.abs(a); //Ternary Operator to run if b is valid
  //Is this ternary operator only checking if the variable b exists?
}

//Least Common Multiple = Smallest number that is divisible by both numbers
//Euclidean Algorithm
function scm(a, b) {
  return (a * b) / gcd(a, b);
}

//Iterate through each part of the array to find the LCM overall
function smallestCommons(arr) {
  arr = arr.sort();
  result = 1;
  for (var i = arr[0]; i <= arr[1]; i++) {
    //I am not quite sure what is happening in this for loop.        
    result = scm(result, scm(result, i));
  }
  return result;
}

document.write('<pre>' + smallestCommons([1, 5]) + '</pre>');
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:2)

Is this ternary operator only checking if the variable b exists?

符号仅用于检查它是否为真值,如Blazemonger所述。但是,它特别适用于在满足基本条件(即b = 0)时停止递归。

I am not quite sure what is happening in this for loop.

循环评估从arr[0]arr[1]的所有数字的最小公倍数,一次取一个数字。这样做是为了避免在数字很大的情况下超出整数限制。

评估基于以下事实:对于三个整数a,b和c,LCM(a, b, c) = LCM(LCM(a, b), c)LCM(1, x) = x。因此,在每个步骤中,循环都会评估已处理零件的LCM和当前项目(即i)。

答案 1 :(得分:2)

我在下面的评论中写了我的答案。更改了一些名称并修复了错误的算法。

/*
When b is not zero, null, undefined, NaN (not a number), or false, then compute greatestCommonDivisor(b, a % b). Otherwise return the absoute value of a.
This will make sense if you step through it with an example. Let's try to find the greatest common divisor of 6 and 9, which we know is 3.

1. a=6, b=9
2. a=9, b=6
3. a=6, b=3
4. a=3, b=0
5. B is falsy!
return absoulte value of a, which is 3.
*/
function greatestCommonDivisor(a, b) {
    return b ? greatestCommonDivisor(b, a % b) : Math.abs(a);
}

function leastCommonMultipleOfTwo(a, b) {
    return (a * b) / greatestCommonDivisor(a, b);
}

/*
No wonder you were confused. The algorithm they gave you was wrong. I fixed it below. Let's look at that with an example.

Let's say we're trying to find the least common multiple of [5, 2, 9]. Logically we know it's 90. (The wrong algorithm gave 60).

The algorithm below takes the array elements one at a time, and finds the LCM of it and whatever LCM we've calculated so far.
Initially we start with calculatedLCM = 1 to get the algorithm started.

1. we look at arr[0], which is 5
calculatedLCM = leastCommonMultipleOfTwo(1,5)
calculatedLCM = 5

2. we look at arr[1], which is 2
calculatedLCM = leastCommonMultipleOfTwo(5,2)
calculatedLCM = 10

3. we look at arr[2], which is 9
calculatedLCM = leastCommonMultipleOfTwo(10,9)
calculatedLCM = 90

*/

function leastCommonMultiple(arr) {
    calculatedLCM = 1;
    for (var i = 0; i < arr.length; i++) {
        calculatedLCM = leastCommonMultipleOfTwo(calculatedLCM, arr[i]);
    }
    return calculatedLCM;
}

console.log(leastCommonMultiple([5, 2, 9]));

答案 2 :(得分:1)

  
    

这个三元运算符是否只检查变量b是否存在?

  

不,它正在检查它是否是truthy value在布尔上下文中计算时转换为true的值。所有值都是真实的,除非它们被定义为假(即,除了false,0,&#34;&#34;,null,undefined和NaN)。

如果未指定b,则其值为undefined,这是一个假值。在提供的代码中,由于使用模数gcb(b, a % b)进行递归,它实际上是检查值是否为0。

  
    

我不太清楚for循环中发生了什么。

  

首先,它可能有助于将其分解为:

var res;
// `arr[0]` is the first value which is assigned to `i`
// The loop will iterate until `i` is equal to
//  the second value `arr[1]`
for (var i = arr[0]; i <= arr[1]; i++) {
  res = scm(result, i);
  result = scm(result, res);
}

然后使用输入[1, 5]

手动逐步执行此操作
  1. 使用:result === 1; i === 1; arr[1] === 5;

    res = scm(1, 1) // res === 1

    result = scm(1, 1) // result === 1

  2. 使用:result === 1; i === 2; arr[1] === 5;

    res = scm(1, 2) // res === 2

    result = scm(1, 2) // result === 2

  3. 使用:result === 2; i === 3; arr[1] === 5;

    res = scm(2, 3) // res === 6

    result = scm(2, 6) // result === 6

  4. 使用:result === 6; i === 4; arr[1] === 5;

    res = scm(6, 4) // res === 12

    result = scm(6, 12) // result === 12

  5. 使用:result === 12; i === 5; arr[1] === 5; 最后一行

    res = scm(12, 5) // res === 60

    result = scm(12, 60) // result === 60

  6. 要做一些观察:

    • 60真的是[1,5]的LCM吗?
    • 如果内部scm调用和外部scm调用都返回相同的值,为什么要对scm进行两次调用?

    我猜测代码没有按预期工作。 :)

答案 3 :(得分:1)

第一个函数是递归函数(在其中调用相同函数的函数)。它将调用自身,直到它被调用,值b等于0.三元运算符就在那里。只要它不为0,测试评估为TRUE,因此执行第一条指令,使用您看到的操作进行递归。每当%b为0时,意味着a可被b整除,它实际上将是最后一次递归调用,三元测试将评估为FALSE并返回a的值。

第二个函数只是利用第一个函数来使用数学公式来找到最小的公倍数。

第三个函数利用第二个函数来查找一系列数字的scm,初始范围,并且循环正是这样做的,变量i从范围的下边界到上边界迭代。

相关问题