30-seconds-code——math

英文文章来源于:https://github.com/Chalarangelo/30-seconds-of-code/blob/master/README.md

Math

数组求和 (arraySum)

返回数字数组的和.

Array.reduce() 加每一个value到累加器, 初始值为 0.

const arraySum = arr => arr.reduce((acc, val) => acc + val, 0);
// arraySum([1,2,3,4]) -> 10

数组求平均值( arrayAverage)

返回一个数组的平均值.

Array.reduce() 加每一个value到累加器, 初始值为 0, 除以数组的 length .

const arrayAverage = arr => arr.reduce((acc, val) => acc + val, 0) / arr.length;
// arrayAverage([1,2,3]) -> 2

clampNumber

Clamps num within the inclusive lower and upper bounds.

lower > upper, 交换它们.
num 在 [lower, upper] 范围内, 返回 num.
否则, 返回离它最近的边界数字.

const clampNumber = (num, lower, upper) => {
  if(lower > upper) upper = [lower, lower = upper][0];
  return (num>=lower && num<=upper) ? num : ((num < lower) ? lower : upper) 
}
// clampNumber(2, 3, 5) -> 3
// clampNumber(1, -1, -5) -> -1
// clampNumber(3, 2, 4) -> 3

交换两个数字(自定义)

实现两个数字的交换


var a = 2, b = 3;

b = [a, a = b][0]

output: a->3  b->2

ES6:

[a, b] = [b, a]

output: a->3  b->2

collatz

实现 collatz 算法.

如果 n 偶数, 返回 n/2. 否则, 返回 3n+1.

const collatz = n => (n % 2 == 0) ? (n / 2) : (3 * n + 1);
// collatz(8) --> 4
// collatz(5) --> 16

digitize

将一个数字转化为数字数组.

将数字转化为字符串, 用spread 操作符([...string]) 将字符串转变为字符串数组.
Array.map()parseInt() 将字符串组的元素转化为数字.

const digitize = n => [...''+n].map(i => parseInt(i));
// digitize(2334) -> [2, 3, 3, 4]

距离(distance)

返回两点间的距离.

Math.hypot() 计算两点间的几何距离.

const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
// distance(1,1, 2,3) -> 2.23606797749979

阶乘(factorial)

返回一个属的阶乘.

使用递归.
如果 n <= 1, 返回 1.
否则, 返回乘以 n - 1 阶乘.
如果 n 负数,抛出异常.

const factorial = n =>
  n < 0 ? (() => { throw new TypeError('Negative numbers are not allowed!') })()
  : n <= 1 ? 1 : n * factorial(n - 1);
// factorial(6) -> 720

斐波那契数列(fibonacci)

生成一个由斐波那契数列数字组成的数组.

创建一个指定长度的空数组, 初始化前两个元素的值为 (0 , 1).
Array.reduce() 向数组中添加数组元素, 从第三个元素开始,每个元素的值为前两个元素的和.

const fibonacci = n =>
  Array.from({ length: n}).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
// fibonacci(5) -> [0,1,1,2,3]

fibonacciCountUntilNum

返回[0 , num ]范围内Fibonacci数目.

使用数学公式计算到 num 的Fibonacci数目.

const fibonacciCountUntilNum = num =>
  Math.ceil(Math.log(num * Math.sqrt(5) + 1/2) / Math.log((Math.sqrt(5)+1)/2));
// fibonacciCountUntilNum(10) -> 7

fibonacciUntilNum

返回一个到 num 的Fibonacci数组.

创建一个指定长度的数组, 初始化前两个元素为 (0 , 1).
Array.reduce() 向数组中添加数组元素, 从第三个元素开始,每个元素的值为前两个元素的和.
使用数学公式计算到 num 的Fibonacci数目,该数字即为数组的长度.

const fibonacciUntilNum = num => {
  let n = Math.ceil(Math.log(num * Math.sqrt(5) + 1/2) / Math.log((Math.sqrt(5)+1)/2));
  return Array.from({ length: n}).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
}
// fibonacciUntilNum(15) -> [0,1,1,2,3,5,8,13]

最大公约数 (gcd)

求两个数间的最大公约数.

用递归.
y 等于 0 返回 x.
否则, 返回 gcd(y, x%y).

const gcd = (x, y) => !y ? x : gcd(y, x % y);
// gcd (8, 36) -> 4

汉明距离 (hammingDistance)

注:它是使用在数据传输差错控制编码里面的,在信息论中用到较多。

计算两个等长字符串的汉明距离。

用异或(XOR)运算符 (^) 去找出两个数字对应位不同的数量, 用 toString(2) 将字符串转为二进制.
计算并返回字符串中为1的数量, 用 match(/1/g) 去匹配.

const hammingDistance = (num1, num2) =>
  ((num1 ^ num2).toString(2).match(/1/g) || '').length;
// hammingDistance(2,3) -> 1

inRange

判断一个数字是否在给定的范围内.

用算术比较来判断给定的数字是否在指定的方位内.
若第二个参数 end 未被指定,这个范围将是 [0 , start] .

const inRange = (n, start, end=null) => {
  if(end && start > end) end = [start, start=end][0];
  return (end == null) ? (n>=0 && n<start) : (n>=start && n<end);
}
// inRange(3, 2, 5) -> true
// inRange(3, 4) -> true
// inRange(2, 3, 5) -> false
// inrange(3, 2) -> false

isArmstrongNumber (阿姆斯特朗数的判断)

判断一个给定的数字是否是 Armstrong 数字.

所谓Armstrong数,就是n位数的各位数的n次方之和等于该数,如:

153=13+53+3^3
1634=14+64+34+44

将给定的数字转换为数字数组. 用 Math.pow() 为每个数字取合适的指数,然后求和. 如果总和等于数字本身返回 true,否则,返回 false.

const isArmstrongNumber = digits => 
  ( arr => arr.reduce( ( a, d ) => a + Math.pow( parseInt( d ), arr.length ), 0 ) == digits ? true : false )( ( digits+'' ).split( '' ) );
// isArmstrongNumber(1634) -> true
// isArmstrongNumber(371) -> true
// isArmstrongNumber(56) -> false

isDivisible

判断第一个数字参数能否被第二个数字参数整除.

用模操作符 (%) 判断余数是否为 0.

const isDivisible = (dividend, divisor) => dividend % divisor === 0;
// isDivisible(6,3) -> true

isEven

如果被给定的数字是偶数,返回 true ,否则, false.

用模操作符 (%) 判断一个数字是奇数还是偶数.
是偶数返回 true,是奇数返回 false .

const isEven = num => num % 2 === 0;
// isEven(3) -> false

isPrime

判断给定的数字是否为素数.

判断从 2 到被给定数的开平方的范围内.
如果范围内的任何数字整出被给定的数返回 false, 否则返回 true, 除非给定数字小于 2.

const isPrime = num => {
  const boundary = Math.floor(Math.sqrt(num));
  for (var i = 2; i * i <= boundary; i++) if (num % i == 0) return false;
  return num >= 2;
};
// isPrime(11) -> true
// isPrime(12) -> false

素数 (primes)

生成到 num 的素数, 用 Sieve of Eratosthenes 算法.

生成一个在 [2, num] 范围内的素数数组. 用 Array.filter() 过滤出能被 [2, √num] 间任意整数整除的数字.

const primes = num => {
  let arr =  Array.from({length:num-1}).map((x,i)=> i+2), 
    sqroot  = Math.floor(Math.sqrt(num)),
    numsTillSqroot  = Array.from({length:sqroot-1}).map((x,i)=> i+2);
  numsTillSqroot.forEach(x => arr = arr.filter(y => ((y%x)!==0)||(y==x)));
  return arr; 
}
// primes(10) -> [2,3,5,7] 

最小公倍数(lcm)

返回两个数的最小公倍数.

用最大公约数 (GCD) 运算式和 Math.abs() 来求最小公倍数.
最大公约数 (GCD) 使用递归.

const lcm = (x,y) => {
  const gcd = (x, y) => !y ? x : gcd(y, x % y);
  return Math.abs(x*y)/(gcd(x,y));
};
// lcm(12,7) -> 84

取中值(median)

返回数字数组中的中间位置数字.

Array.sort() 去排序数组,找出中间值.
如果数组的 length 为奇数,返回中间一位数, 否则返回中间两个数的平局数.

const median = arr => {
  const mid = Math.floor(arr.length / 2), nums = [...arr].sort((a, b) => a - b);
  return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2;
};
// median([5,6,50,1,-5]) -> 5
// median([0,10,-2,7]) -> 3.5

回文字符串(palindrome)

Returns true if the given string is a palindrome, false otherwise.

将字符串转为小写 toLowerCase() 并且用 replace() 移除非字母字符.
split('') 将字符串分割为字符数组, 紧接着用 reverse() 反转字符串,用 join('') 拼接字符数组为字符串,然后和原字符串比较.

const palindrome = str => {
  const s = str.toLowerCase().replace(/[\W_]/g,'');
  return s === s.split('').reverse().join('');
}
// palindrome('taco cat') -> true

百分位(percentile)

公式为 p=100*i/n

用百分位数公式计算给定数组中有多少个数字小于或等于给定值.

Array.reduce() 去计算给定数组中有多少个数字小于等于给定的值.

const percentile = (arr, val) =>
  100 * arr.reduce((acc,v) => acc + (v < val ? 1 : 0) + (v === val ? 0.5 : 0), 0) / arr.length;
// percentile([1,2,3,4,5,6,7,8,9,10], 6) -> 55

幂集 (powerset)

返回一个指定数组的幂集.

Array.reduce() 结合 Array.map() 迭代所有的元素然后生成一个包含所有元素集合的数组.

const powerset = arr =>
  arr.reduce((a, v) => a.concat(a.map(r => [v].concat(r))), [[]]);
// powerset([1,2]) -> [[], [1], [2], [2,1]]

randomIntegerInRange

返回指定范围的随机整数.

Math.random() 生成一个随机数,并将其映射到指定范围内, 用 Math.floor() 将其转化为一个整数.

const randomIntegerInRange = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
// randomIntegerInRange(0, 5) -> 2

randomNumberInRange

返回指定范围内的随机数.

Math.random() 生成一个随机数, 使用乘法将其映射到所需的范围内.

const randomNumberInRange = (min, max) => Math.random() * (max - min) + min;
// randomNumberInRange(2,10) -> 6.0211363285087005

四舍五入(round)

数字四舍五入指定位数.

Math.round() 和模板字面量四舍五入一个数字指定位数.
如果省略第二个参数, decimals 默认为0.

const round = (n, decimals=0) => Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);
// round(1.005, 2) -> 1.01

标准差(standardDeviation)

返回一组数字的标准差.

Array.reduce() 计算平均值、方差和放长的总和,然后计算标准差.
你可以省略第二个参数来获得样本标准差或将其设为true来获得总体标准差.

const standardDeviation = (arr, usePopulation = false) => {
  const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
  return Math.sqrt(
    arr.reduce((acc, val) => acc.concat(Math.pow(val - mean, 2)), [])
       .reduce((acc, val) => acc + val, 0) / (arr.length - (usePopulation ? 0 : 1))
  );
};
// standardDeviation([10,2,38,23,38,23,21]) -> 13.284434142114991 (sample)
// standardDeviation([10,2,38,23,38,23,21], true) -> 12.29899614287479 (population)

更多关于30-seconds-code中文翻译
https://github.com/lvzhenbang/article/blob/master/js/30-seconds-code/index.md

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容