JavaScript中不具备的数学函数,我们将探索 JavaScript 中缺少的一些数学函数,以及我们如何为它们编写函数。JavaScript Math 对象包含一些非常有用和强大的数学运算,可用于 Web 开发,但它缺少大多数其他语言提供的许多重要运算(例如 Haskell,它有大量的运算)。

JavaScript 中缺少数学方法:Sum

你可能还记得在学校,“sum”是“add”的同义词。例如,如果我们将数字 1、2 和 3 相加,它实际上意味着1 + 2 + 3

我们的sum函数将涉及对数组中的所有值求和。

有两种写这个函数的方法:我们可以使用for循环,或者我们可以使用reduce函数。

使用for循环:

function sum(array){
    let total = 0
    for(let count = 0; count < array.length; count++){
        total = total + array[count]
    }
    return total
}

使用reduce功能:

function sum(array){
    return array.reduce((sum, number) => sum + number, 0)
}

这两个函数的工作方式完全相同(该reduce函数只是一个内置for循环),并且将返回相同的数字(给定相同的数组)。但是reduce功能要简洁得多。

所以,例如:

sum([1,2,3,4]) === 10 // 1 + 2 + 3 + 4

sum([2,4,6,8]) === 20 // 2 + 4 + 6 + 8

能够对数字列表求和可能是 JavaScriptMath对象中最有用和最需要的“缺失”数学运算。同样,sum函数是一个很好的检查工具。例如,在数独游戏中,我们可以通过检查列/行加起来是否为 45 (1 + 2 + 3 + 4 +…+ 9) 来检查用户是否在该列或行中没有重复。如果我们想计算总账单,该函数在在线购物应用程序中也能很好地工作——假设所有价格都存储在一个数组中。

在购物应用程序示例之后,这里是我们如何在代码中使用它的示例:

const prices = [2.80, 6.10, 1.50, 1.00, 8.99, 2.99]

function totalCost(prices){
    return prices.reduce((sum, item) => sum + item, 0)
}

JavaScript 中缺少数学方法:产品

我们的product函数将以与函数类似的方式工作sum,不同之处在于,我们不是将列表中的所有数字相加,而是将它们相乘

再一次,我们可以使用与第一个函数for几乎相同的循环:sum

function product(array){
    let total = 1
    for(let count = 0; count < array.length; count++){
        total = total * array[count]
    }
    return total
}

请注意,我们使用而不是初始化total变量,否则我们将始终以 0 结尾。10total

但该reduce函数在这种情况下仍然有效,并且仍然是编写函数的一种更简洁的方法:

function product(array){
    return array.reduce((total, num) => total*num, 1)
}

这里有些例子:

product([2,5,8,6]) === 480 // 2 x 5 x 8 x 6

product([3,7,10,2]) === 420 // 3 x 7 x 10 x 2

这个函数的用途可能看起来并不明显,但我发现当尝试在一次计算中进行多次转换时它们非常有用。例如,如果您想找到十包苹果的美元价格(每公斤苹果 1.50 元),而不是使用巨大的乘法和,将所有值存储在一个数组中并使用product我们刚刚编写的函数。

数组的一个例子是这种格式:

const pricePerKg = 1.50
const numberOfKg = 10
const conversionRate = 1.16
const conversion = [1.50, 10, 1.16]

const USprice = product([pricePerKg,numberOfKg,conversionRate])

JavaScript 中缺少数学方法:奇数和偶数

这些函数将接受一个数字,它可以是数组长度的形式,并返回truefalse取决于数字是奇数还是偶数。

偶数必须能被二整除,奇数则相反,不能被二整除。这将是功能的关键部分。

例如,Haskell 内置了这些函数,这让事情变得容易多了,尤其是你可以这样写:

even 29
<< false

odd 29
<< true

另一方面,Ruby 以方法的形式提供这些功能。这仍然更容易编写:

29.even?
<< false

29.odd?
<< true

在 JavaScript 中编写这些函数的最简单方法是使用余数运算符,% . 当一个数字除以另一个数字时,这将返回余数。例如:

11 % 3 === 2 // 11 divide 3 === 3 remainder 2

这是我们的even函数的示例:

function even(number){
    return number % 2 === 0
}

如我们所见,我们有一个even函数,它以一个数字作为参数并根据条件返回一个布尔值:

number % 2 === 0

当数字除以二时,如果余数等于零,我们知道它可以被二整除并true返回。例如:

even(6) === true

even (9) === false

这是我们的odd函数的示例:

function odd(number){
    return number % 2 !== 0
}

这两个函数非常相似:以一个数字作为参数,根据条件返回一个布尔值:

number % 2 !== 0

如果数字除以 2 的余数不等于零,则该数字为奇数,true将被返回。例如:

odd(7) === true

odd(114) === false

能够检查一个数字是奇数还是偶数是至关重要的,而且非常简单。起初它可能看起来并不那么重要,但它可以作为一种很好的输入验证技术——例如,使用数组长度,或者简单地检查两人游戏的获胜者。您可以跟踪已经玩了多少轮,如果数字是奇数,则玩家 1 获胜,如果是偶数,则玩家 2 获胜——假设第一轮计为 1。

这些功能是可以互换的,我们很可能只需要使用一个。然而,拥有这两个函数可以更容易地跟踪truefalse逻辑,尤其是在大块代码中。

以下是我们如何对上面的示例进行编码:

function checkWinner(gamesPlayed){
    let winner
    if(odd(gamesPlayed)){
        winner = "player1"
    }
    else{
        winner = "player2"
    }
    return winner
}

JavaScript 中缺少数学方法:triangleNumber

三角形数字听起来比实际更花哨。它们只是直到某个数字的所有整数的总和。

例如,这是第五个三角形数:5 + 4 + 3 + 2 + 1 = 15。

这链接回我们之前的数独示例。我们要检查所有数字是否唯一,我们可以通过检查它们是否匹配 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 的结果来做到这一点。当然,这是第九个三角数!

当然,我们可以使用for循环编写函数,如下所示:

function triangleNumber(number){
    let sum = 0
    for(let i=1; i < number + 1; i++){
        sum = sum + i
    }
    return sum
}

然而,这将是一个非常低效的决定,因为有一个非常简单的计算三角形数的公式:0.5 x (number) x (number + 1).

因此,我们函数的最高效版本应该如下所示:

function triangleNumber(number){
    return 0.5 * number * (number + 1)
}

以下是我们如何使用它的一些示例:

triangleNumber(7) === 28 // 0.5 x 7 x 8

triangleNumber(123) === 7626 // 0.5 x 123 x 124

JavaScript 中缺少数学方法:阶乘

自然数(任何严格大于 0 的整数)的阶乘是所有小于或等于该数的数的乘积。例如:3阶乘(用 表示3!)是3 x 2 x 1 = 6

sumandproduct函数类似,有两种创建factorial函数的方法:使用for循环和使用递归。

以下是我们如何factorial使用for循环创建我们的函数:

function factorial(number){
  let total = 1
  for (let i = 1; i < number+1; i++){
    total = total * i
  }
  return total
}

此函数循环遍历从 1 到数字(每次递增)的所有数字,并将总数乘以每个数字,然后返回最终总数(数字阶乘)。

下面是我们如何factorial使用递归创建我们的函数:

function factorial(number){
  if (number <= 0){
    return 1
  }
  else{
    return number * factorial(number - 1)
  }
}

在这个函数中,我们的基本情况是零,因为0!令人惊讶的是一(对此的证明实际上非常有趣)。这意味着,当数字通过函数时,只要它不为零,它就会乘以factorial(number - 1)

为了帮助准确理解此函数在每次传递时的作用,跟踪算法可能会有所帮助。这是用 3 跟踪的算法:

factorial(3) === 3*factorial(2) === 3*2*factorial(1) === 3*2*1*factorial(0) === 3*2*1*1 === 3*2*1 === 6

无论哪种方式,这两个函数都将返回相同的值。例如:

factorial(5) === 120 // 5 x 4 x 3 x 2 x 1

JavaScript 中缺少数学方法:因素

因子成对出现,每一对相乘形成原始数。例如:

  • 10的因数是:1和10;2 和 5。
  • 18的因数是:1和18;2 和 9;3 和 6。

我们希望我们的factors函数接受一个数字,并返回一个包含其所有因子的数组。这个函数的写法有很多种,但最简单的方法是使用命令式的方法,例如:

function factors(number){
    let factorsList = []
    for(let count = 1; count < number+1; count++){
        if(number % count === 0){
            factorsList.push(count)
        }
    }
    return factorsList
}

首先,我们创建数组——开始时将其留空。然后我们使用for循环遍历从 1 到数字本身的每个整数,并且在每次通过时我们检查数字是否可以被整数整除(或者count在这种情况下)。

如您所见,为了检查可分性,我们mod再次使用符号。如果数字可以被整数整除,它就是一个因子,可以被推入我们的数组。

然后返回数组,每次运行该函数时,都会按升序返回一个因子数组。例如:

factors(50) === [1,2,5,10,25,50]

找到一个数字的因数可能非常有用,尤其是当您需要制定组时——例如在在线游戏中,当您需要每个团队中的用户数量相等时。例如,如果您有 20 个用户并且每个团队需要 10 个玩家,您可以使用factors函数将这 10 个玩家与两个团队匹配。同样,如果每队需要四名球员,您可以使用该factors功能将四人匹配成五队。

在实践中,它可能看起来像这样:

function createTeams(numberOfPlayers, numberOfTeams){
    let playersInEachTeam
    if(factors(numberOfPlayers).includes(numberOfTeams)){
        playersInEachTeam = numberOfPlayers / numberOfTeams
    }
    else{
        playersInEachTeam = "wait for more players"
    }
    return playersInEachTeam
}

JavaScript 中缺少数学方法:isPrime

这是您在学校学到的最早条件之一,但在日常生活中并不经常使用。简而言之,如果一个数有两个不同的因数,并且总是一个和它本身,那么这个数就是质数。质数开始:2、3、5、7、11、13、17、19 ……等等直到无穷大。

它最初可能看起来像一个复杂的函数——如果我们不只是编写了一个非常有用的函数,它可能确实如此factors。如前所述,如果一个数有两个不同的因子,那么它就是质数,所以我们的函数就这么简单:

function isPrime(number){
    return factors(number).length === 2
}

这将根据其因子列表的长度是否为二返回一个布尔值——换句话说,它是否有两个因子。

在实践中,它看起来像这样:

isPrime(3) === true

isPrime(76) === false

isPrime(57) === true

继续上面的“分组用户”示例,如果用户的数量是质数,我们不能将它们平均分组(除非我们只有一组,但这会破坏示例的目标),这意味着我们将有等待另一个用户加入。所以,我们可以在这样的函数中使用它:

function addUsers(users){
    if(isPrime(users)){
        wait = true
    }
    else{
        wait = false
    }
}

JavaScript 中缺少数学方法:gcd(最大公约数)

有时被称为“最大公因数”,最大公因数运算找到两个数共享的最大因数。

例如:

  • 12和15的最大公约数是3。
  • 8和4的最大公约数是4。

解决这个问题的一个简单方法是列出每个数字的所有因数(使用我们上面不可思议的函数)并比较这些列表。然而,比较列表需要一些非常漂亮但效率低下的数组操作。

但这里有一个例子:

function gcd(number1, number2){
    let inCommon = []
    for(let i of factors(number1)){
        if(factors(number2).includes(i)){
            inCommon.push(i)
        }
    }
    return inCommon.sort((a,b)=> b - a)[0]
}

在这里,我们将一个空数组分配给变量inCommon并循环遍历因子数组number1(使用我们之前的函数)。如果 factors 数组number2包含当前通道中的项目,我们将其推入我们的inCommon数组。

一旦我们有了一个包含两个数字共有的所有因子的数组,我们就返回按降序排列的数组的第一个值。换句话说,我们返回最大公约数。

可以想象,如果我们还没有创建该factors函数,那么为此编写的代码将会非常庞大​​。

一种更简洁但更难的方法是使用递归。这是一个非常著名的算法,称为欧几里德算法:

function gcd(number1, number2){
    if(number2 === 0){
        return number1
    }
    else{
        return gcd(number2, number1%number2)
    }
}

我们这里的基本情况number2等于 0,此时number1是最大公约数。否则,GCD 是 GCD除以number2的余数。number1number2

同样,这两个函数将返回相同的东西。例如:

gcd(24, 16) === 8

gcd(75, 1) === 1

avaScript 中缺少数学方法:lcm(最小公倍数)

最小公倍数在与最大公约数相似的波长上工作,而是找到两个数字都是其因数的最小整数。

例如:

  • 2和6的最小公倍数是6。
  • 4和15的最小公倍数是60。

不幸的是,对于这个函数,我们不能只创建一个包含每个数字的所有倍数的数组,因为这将是一个无限列表。

但是,我们可以使用一个非常有用的公式来计算最小公倍数:

(number1 x number2) / the Greatest Common Divisor of the two numbers

要检查公式,您可以尝试使用上面的示例。2和6的LCM:

(2 x 6)/gcd(2,6) = 12/2 = 6

幸运的是,我们刚刚创建了一个gcd函数,所以创建这个函数非常简单:

function lcm(number1, number2){
    return (number1*number2)/gcd(number1, number2)
}

就是这样!我们需要做的就是返回上面的公式,它应该可以工作:

lcm(12, 9) === 36 // (12 x 9)/3

这个函数可能没有任何明显的用途,但我经常发现它非常适合两个事件以不同的时间间隔发生的情况,这意味着我们可以使用 LCM 找出两个事件何时同时发生。

例如,如果一个图像被编程为每六秒出现一次,一段文本被编程为每八秒出现一次,那么图像和段落将在第 24 秒第一次同时出现。

JavaScript中不具备的数学函数 相关

SQLite在Pyhont中的使用

更具有函数化的5种JavaScript写法

优惠券