node.js - 猫鼬。正确增量四舍五入到 2 位数
问题描述
猫鼬:v5.11.11,Nodejs:v12.18.3
const Schema = new Schema({
total: {
type: Number,
set: v => Math.round(v * 100) / 100,
default: 8.01,
}
let myController = (id, addValue) => model.findByIdAndUpdate(id, { $inc: { total: addValue } })
myController(111, 0.29)
我们在 db { total : 8.299999999999999 } 中得到一个值,而不是 8.30
解决方案
对于解决方案,setter
如果您使用 ,您将不会被触发findByIdAndUpdate
,而是您需要查询对象,编辑它然后保存它。
以下是关于为什么 8.01 + 0.29 != 8.30 的解释。
JavaScript 数字始终存储为双精度浮点数,遵循国际 IEEE 754 标准。这就是为什么浮点运算并不总是 100% 准确的原因!
让我们深入研究一下。我们可以像这样将十进制数转换为二进制数:
// output: "1000.010011001100110011001100110011001100110011001101"
8.30.toString(2)
如您所见,总共有 52 个数字字符。
我们可以使用以下函数将二进制转换回十进制:
function transformIntegerPart(str) {
let ret = 0;
let len = str.length;
str.split('').forEach((d, i) => {
if (d === '1') ret += Math.pow(2, len - i - 1);
});
return ret;
}
function transformDecimalPart(str) {
let ret = 0;
str.split('').forEach((d, i) => {
if (d === '1') ret += Math.pow(2, -1 - i);
});
return ret;
}
// for 8.30,
// real integer part is
transformIntegerPart('1000') // output: 8
// real decimal part is
transformDecimalPart('010011001100110011001100110011001100110011001101') // output: 0.3000000000000007 (not actually, javascript adjust this precision automatically)
// so, the real 8.30 in javascript is 8.3000000000000007...
8.30.toPrecision(20) // output: 8.3000000000000007105
现在,我们可以回答您的问题:
// output: "1000.0000001010001111010111000010100011110101110000101"
8.01.toString(2);
// output: "0.010010100011110101110000101000111101011100001010001111"
0.29.toString(2);
let integerPart = transformIntegerPart('1000') + transformIntegerPart('0');
console.log(integerPart); // output: 8
let decimalPart = transformDecimalPart('0000001010001111010111000010100011110101110000101') + transformDecimalPart('010010100011110101110000101000111101011100001010001111');
console.log(decimalPart); // output: 0.29999999999999977
// output: 8.299999999999999
console.log(integerPart + decimalPart);
推荐阅读
- c# - XML 反序列化为嵌套的对象数组。再次
- passport.js - 使用护照从谷歌 Oauth 制作更大的谷歌个人资料图片
- c++ - 使用邻接矩阵和列表的 C++ 图形
- python - 在进行机器学习时如何保留行的唯一 ID?
- python-3.x - 使用 selenium 下载动态生成的 pdf
- php - 如何让 .ics 为 Outlook(Laravel 邮件程序)工作?
- javascript - 如何使 Uc 浏览器无法访问我的网站
- cdn - pagespeed测试分数是否考虑了CDN?
- r - 将电子表格中的值替换为多列分配的十分位值 (1-10)
- python - Python中的递归使用函数参数来跟踪但返回值丢失