覆盖 90% 编程问题的五大数学运算
Source: Dev.to
经过多年构建工具和审查代码,我发现生产软件中绝大多数的数学运算可以归结为五类。你不需要数学学位,只需要在这五个领域熟练掌握。
1. 百分比计算
百分比无处不在:折扣、税金、小费、进度条、分析仪表板、A/B 测试结果。
// What is X% of Y?
const percentOf = (percent, total) => (percent / 100) * total;
// What percentage is X of Y?
const whatPercent = (part, total) => (part / total) * 100;
// Percentage change from A to B
const percentChange = (oldVal, newVal) =>
((newVal - oldVal) / oldVal) * 100;百分比变化公式是开发者最常弄错的。分母是 旧 值,而不是新值。把 50 提升到 75 是 50 % 的增长。把 75 降到 50 是 33.3 % 的下降。这种不对称性会让人困惑。
2. 线性插值
将一个值从一个范围映射到另一个范围。常用于动画、数据可视化、颜色渐变、音频处理和传感器校准。
function lerp(value, inMin, inMax, outMin, outMax) {
return outMin + ((value - inMin) * (outMax - outMin)) / (inMax - inMin);
}
// Map a 0‑1023 sensor reading to 0‑100%
lerp(512, 0, 1023, 0, 100); // 50.05%
// Map a 0‑1 progress value to a 200‑800px width
lerp(0.75, 0, 1, 200, 800); // 650px逆向函数(用于确定一个值在范围中的位置)同样有用:
function inverseLerp(value, min, max) {
return (value - min) / (max - min);
}
// Where does 650 fall in the 200‑800 range?
inverseLerp(650, 200, 800); // 0.753. 四舍五入和精度
JavaScript 的浮点运算会产生著名的惊人结果:
0.1 + 0.2 // 0.30000000000000004一个实用的显示修正方法:
function round(value, decimals) {
return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
round(0.1 + 0.2, 2); // 0.3对于金融计算,绝不要使用浮点数。使用整数(分):
// 错误写法
const price = 19.99;
const tax = price * 0.08; // 1.5992000000000002
// 正确写法
const priceCents = 1999;
const taxCents = Math.round(priceCents * 0.08); // 160
const totalCents = priceCents + taxCents; // 2159
const totalDollars = (totalCents / 100).toFixed(2); // "21.59"4. 模运算
取模运算符 (%) 用于在数组中循环、值的环绕、判断奇偶以及时间计算。
// Cycle through an array
const colors = ['red', 'green', 'blue'];
const color = colors[index % colors.length];
// Wrap a value within bounds
function wrap(value, min, max) {
const range = max - min;
return ((value - min) % range + range) % range + min;
}
// Convert seconds to hours:minutes:seconds
function formatTime(totalSeconds) {
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
return `${hours}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
}wrap 中的双取模用于处理负数。JavaScript 的 % 运算符对负被除数会返回负结果,这通常不是我们想要的。
5. 基本统计
均值、中位数和标准差用于监控、告警、数据分析和性能测量。
const mean = arr => arr.reduce((a, b) => a + b, 0) / arr.length;
const median = arr => {
const sorted = [...arr].sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2
? sorted[mid]
: (sorted[mid - 1] + sorted[mid]) / 2;
};
const stdDev = arr => {
const avg = mean(arr);
const variance = mean(arr.map(x => (x - avg) ** 2));
return Math.sqrt(variance);
};标准差告诉你数据的离散程度。对于监控而言,如果某个指标偏离均值超过 2 个标准差,就说明出现了异常。这是大多数异常检测系统的基础。
组合它们
真实的问题往往涉及多个操作。比如“为文件上传显示带有百分比和预计剩余时间的进度条”:
function uploadProgress(bytesUploaded, totalBytes, elapsedMs) {
const percent = whatPercent(bytesUploaded, totalBytes);
const rate = bytesUploaded / elapsedMs; // bytes per ms
const remaining = (totalBytes - bytesUploaded) / rate;
return {
percent: round(percent, 1),
barWidth: lerp(percent, 0, 100, 0, 300), // 300px bar
remainingSeconds: Math.ceil(remaining / 1000)
};
}在进行任何数学计算并提供逐步解答时,我会使用位于 . 的求解器。它能够处理从基础算术到代数和统计的所有内容——快速、免费,并且会展示解题过程。