最近我在做数据可视化和图形图像渲染相关的技术研究,而图形图像涉及到许多几何图形的向量运算,我们求一个向量的模,需要计算每个坐标分量的平方和,然后开根号。
一般来说,我们使用类似如下的代码:
function length(v) {
const dimension = v.length;
let ret = 0;
for(let i = 0; i < dimension; i++) {
ret += v[i] ** 2;
}
return Math.sqrt(ret);
}
const v1 = [3, 4];
console.log(length(v1)); // 5
但是,在 ES2015 中,提供了Math.hypot
方法,来计算参数的平方根。
const v1 = [3, 4];
console.log(Math.hypot(...v1)); // 5
目前除了 IE 外,其他的浏览器都支持这个方法。
?? 冷知识 —— Math.hypot 的坑:你可能会认为 Math.hypot 是内置函数,它的性能应该要比用 Math.sqrt 好,但是实际上并不是这样。我们写一段测试脚本:
function length(v) {
const dimension = v.length;
let ret = 0;
for(let i = 0; i < dimension; i++) {
ret += v[i] ** 2;
}
return Math.sqrt(ret);
}
// Math.hypot
const v1 = Array(10).fill(0).map(() => Math.random());
const result = Math.hypot(...v1);
//Math.sqrt
const v1 = Array(10).fill(0).map(() => Math.random());
const result = length(v1);
用 jsperf 进行测试,结果令人惊讶,在我的 Chrome 75 下,使用 Math.hypot 竟然比使用 Math.sqrt 慢 40% 左右。
也许是我使用的姿势不对?但是 kangax 大神早在 14 年的时候就写过更多 case 来测试:
结果。。。
所以一个 ES2015 开始支持的数学函数,又是很常用的运算,却没有多少人使用,也没有多少人介绍它,也是有理由的 —— 性能捉急。
不过 hypot 性能不如 sqrt,也并不意味着它完全不可用。
在某些情况下,使用 hypot 能得到 sqrt 无法得到的结果。比如特别大的数或者特别小的数值下:
Math.hypot(2e200, 3e200); // 3.6055512754639894e+200
Math.sqrt(2e200 ** 2 + 3e200 ** 2); // Infinity
Math.hypot(2e-200, 3e-200); // 3.6055512754639893e-200
Math.sqrt(2e-200 ** 2 + 3e-200 ** 2); // 0
所以,如果我们要处理很大的数或很小的数时,可以使用 Math.hypot,在一般情况下,还是使用 Math.sqrt 为好。例如:
const result = Math.sqrt(x ** 2 + y ** 2);
if(!Number.isFinite(result)) result = Math.hypot(x, y);
关于 Math.hypot 还有什么问题,可以在 issue 中讨论。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!