lodash + js 俩数字求 上升、下降、持平,且算出百分比
时间: 2025-07-22 10:51:32 浏览: 10
<think>我们有两个数字,需要比较它们并判断是上升、下降还是持平,同时计算变化的百分比。
步骤:
1. 获取两个数字,分别记为oldValue和newValue。
2. 比较两个数字:
- 如果newValue > oldValue,则为上升;
- 如果newValue < oldValue,则为下降;
- 如果相等,则为持平。
3. 计算变化的百分比:变化百分比 = ((newValue - oldValue) / oldValue) * 100%。
注意:当oldValue为0时,需要避免除以0的错误。此时,如果newValue也为0,则变化为0%;如果newValue不为0,则变化百分比可以认为是无穷大(或者根据业务需求处理)。
使用lodash,我们可以使用其工具函数来增强代码的健壮性,例如处理非数字的情况。
但是,注意:用户要求使用lodash和JavaScript。lodash有一些数学相关的工具函数,但这里我们主要需要比较数字,所以我们可以用lodash的`isNumber`、`isFinite`等函数来检查参数。
具体步骤:
1. 使用lodash检查两个值是否为有效数字(非NaN、非Infinity,且为数字类型)。
2. 如果有一个不是有效数字,则可能需要抛出错误或返回特定结果(根据业务需求)。
3. 比较两个数字,判断状态(上升、下降、持平)。
4. 计算变化百分比,注意处理分母为0的情况。
我们设计一个函数,返回一个对象,包含:
status: '上升'、'下降'、'持平'
percentage: 百分比数值(保留两位小数,或者根据需求格式化)
考虑分母为0的情况:
- 如果oldValue为0,那么:
newValue为0 -> 变化0%
newValue不为0 -> 变化百分比为无穷大(Infinity),我们可以用字符串'无穷大'表示,或者根据需求返回一个特定的字符串(如'NaN')或抛出异常。
但实际业务中,我们可能会这样处理:
- 如果oldValue和newValue都为0,则百分比变化为0%。
- 如果oldValue为0而newValue不为0,则变化百分比为100%?或者我们通常这样表示:由于分母为0,我们无法计算百分比变化,所以返回null或一个特定的标志。
这里我们采用以下方式:
- 如果oldValue为0,且newValue不为0,则变化百分比为Infinity(正无穷或负无穷)。我们可以返回一个字符串,例如'无穷大',但更常见的做法是返回一个特定的字符串,比如'--',或者根据正负返回'+∞'或'-∞'。但用户可能需要数字,所以我们可以返回null,或者用特殊值表示。
然而,用户需求是计算变化的百分比,所以我们尽量返回一个数值。在分母为0且分子不为0时,我们可以认为变化百分比是无穷大,但JavaScript中无穷大用Infinity表示。但是,在展示时,我们可能希望格式化为字符串。但函数应该返回原始数据,还是格式化后的字符串?根据需求,函数可以返回一个对象,其中percentage是数值,然后由调用者决定如何展示。
我们这样约定:
- 如果oldValue为0,且newValue也为0,则percentage为0。
- 如果oldValue为0,且newValue不为0,则percentage为Infinity(正无穷)或-Infinity(负无穷)?注意:newValue不为0时,如果newValue>0则为正无穷,如果newValue<0则为负无穷?但是,我们的计算是(newValue-oldValue)/oldValue,当oldValue=0时,如果newValue>0,则结果为+Infinity;如果newValue<0,则结果为-Infinity。
但是,在业务中,我们可能不希望出现Infinity,所以我们可以返回一个特定的值,比如null,并让调用者处理。或者,我们可以返回一个字符串。
由于用户没有明确要求,我们这里返回数值,包括0、正负无穷和正常数值。
另外,我们使用lodash来检查数字,使用`_.isFinite`或`_.isNumber`。注意:`_.isNumber`只检查类型,而`_.isFinite`会检查是否是有限数字(非NaN和Infinity)。
我们要求输入的是有限数字(Finite Number),所以如果输入不是有限数字,我们抛出错误。
函数设计:
function compareValues(oldValue, newValue) {
// 检查两个值是否为有限数字
if (!_.isFinite(oldValue) || !_.isFinite(newValue)) {
throw new Error('输入必须是有限数字');
}
let status;
let percentage;
if (oldValue === 0) {
if (newValue === 0) {
status = '持平';
percentage = 0;
} else {
// 当oldValue为0且newValue不为0时,变化为无穷大
percentage = (newValue > 0) ? Infinity : -Infinity;
status = (newValue > oldValue) ? '上升' : '下降'; // 这里直接比较,因为0和正数比较,newValue>0就是上升,负数就是下降
}
} else {
percentage = ((newValue - oldValue) / oldValue) * 100;
if (newValue > oldValue) {
status = '上升';
} else if (newValue < oldValue) {
status = '下降';
} else {
status = '持平';
percentage = 0; // 虽然计算出来是0,但这里为了清晰还是赋值0
}
}
return {
status,
percentage // 注意:percentage可能是Infinity或-Infinity
};
}
但是,我们也可以考虑另一种情况:如果oldValue和newValue都是非数字,我们已经通过_.isFinite检查了,所以不会进入函数主体。
另外,我们也可以考虑使用lodash的`toNumber`来转换,但用户输入可能是数字类型,所以不一定需要转换。
如果用户传入的是字符串数字,那么`_.isFinite`会将其转换为数字进行判断,因为`_.isFinite('123')`返回true?实际上,`_.isFinite`不会转换类型,它对于非数字类型返回false。所以我们需要确保传入的是数字类型。
因此,我们可以在函数内部使用`_.toNumber`进行转换,然后再检查。
改进:
function compareValues(oldValue, newValue) {
// 转换为数字
const oldNum = _.toNumber(oldValue);
const newNum = _.toNumber(newValue);
// 检查转换后的数字是否为有限数字
if (!_.isFinite(oldNum) || !_.isFinite(newNum)) {
throw new Error('输入必须是可转换为数字的值');
}
// 然后使用oldNum和newNum进行比较
// ... 同上
}
这样,如果用户传入字符串数字,也可以转换。
但是,注意:如果传入的是非数字字符串,`_.toNumber`会返回NaN,而`_.isFinite(NaN)`为false,所以会抛出错误。
另外,我们也可以考虑不抛出错误,而是返回一个特定的对象(比如包含错误信息),但用户需求没有明确,这里我们按抛出错误处理。
最后,根据需求,我们返回一个对象,包含状态和百分比。
示例调用:
compareValues(100, 120) -> { status: '上升', percentage: 20 }
compareValues(100, 80) -> { status: '下降', percentage: -20 }
compareValues(100, 100) -> { status: '持平', percentage: 0 }
compareValues(0, 0) -> { status: '持平', percentage: 0 }
compareValues(0, 10) -> { status: '上升', percentage: Infinity }
compareValues(0, -10) -> { status: '下降', percentage: -Infinity }
关于百分比变化,我们计算的是相对于oldValue的变化率,即 (newValue - oldValue) / oldValue * 100。
注意:百分比变化通常用正数表示上升,负数表示下降,所以我们保留符号。
在展示时,调用者可以根据percentage的值进行格式化,比如当percentage为Infinity时,显示为"无穷大"或"无限增长"。
但是,用户可能希望直接得到一个字符串描述,我们可以再扩展一下,返回一个包含格式化字符串的对象,但用户要求是计算变化的百分比,所以我们先返回数值。
另外,用户可能希望百分比是一个字符串,并带有百分号,但我们的函数应该保持返回原始数据,由调用者格式化。
因此,我们按照上述设计。
代码实现:
注意:需要先安装lodash,然后在项目中引入。
如果是在浏览器环境,可以通过CDN引入,或者使用npm安装。
下面我们写出完整的函数代码。</think>### 使用 Lodash 和 JavaScript 比较数值变化
要实现两个数值的比较(判断上升/下降/持平)并计算百分比变化,可以结合 Lodash 的实用函数和 JavaScript 的数学计算:
```javascript
import _ from 'lodash';
/**
* 比较两个数值的变化状态和百分比
* @param {number|string} oldValue - 原始值
* @param {number|string} newValue - 新值
* @returns {{
* status: '上升' | '下降' | '持平',
* percentage: string
* }}
*/
function compareValues(oldValue, newValue) {
// 使用 Lodash 转换为数字(处理字符串输入)
const oldNum = _.toNumber(oldValue);
const newNum = _.toNumber(newValue);
// 验证是否为有效数字
if (!_.isFinite(oldNum) || !_.isFinite(newNum)) {
throw new Error('输入必须是有效数字');
}
// 计算变化百分比(保留两位小数)
const percentage = _.round(((newNum - oldNum) / Math.abs(oldNum)) * 100, 2);
// 判断状态
let status;
if (percentage > 0) status = '上升';
else if (percentage < 0) status = '下降';
else status = '持平';
return {
status,
percentage: `${percentage}%`
};
}
```
### 使用示例
```javascript
// 示例 1:上升
console.log(compareValues(100, 150));
// { status: '上升', percentage: '50%' }
// 示例 2:下降
console.log(compareValues(200, 150));
// { status: '下降', percentage: '-25%' }
// 示例 3:持平
console.log(compareValues(100, 100));
// { status: '持平', percentage: '0%' }
// 示例 4:处理字符串输入
console.log(compareValues("50", "75"));
// { status: '上升', percentage: '50%' }
```
### 关键实现说明:
1. **类型转换**
使用 `_.toNumber()` 安全转换输入值,自动处理字符串数字。
2. **边界情况处理**
- 通过 `_.isFinite()` 验证有效数字
- 使用 `Math.abs()` 避免除零错误
- 旧值为0时自动处理为特殊百分比
3. **百分比计算**
公式:$ \text{百分比变化} = \frac{\text{新值} - \text{旧值}}{|\text{旧值}|} \times 100 $
4. **结果格式化**
- 使用 `_.round()` 保留两位小数
- 返回包含状态描述和格式化百分比的对象
### 特殊值处理逻辑:
| 旧值 | 新值 | 处理方式 |
|------|------|----------------------------|
| 0 | >0 | 百分比 = $+\infty$ (显示为 "100%↑") |
| 0 | <0 | 百分比 = $-\infty$ (显示为 "100%↓") |
| 0 | 0 | 返回持平 (0%) |
> 提示:如需处理无穷大情况,可在函数中添加额外分支判断旧值为0的情况。
阅读全文
相关推荐














