JavaScript中舍入错误的测试
如何确定JavaScript中的数字是否太大(如果执行数学运算,将导致舍入错误) 例如,我有一个设置百分比格式的函数。如果它不能正确格式化传入的值,我希望它返回的值与传入的值完全相同JavaScript中舍入错误的测试,javascript,jquery,biginteger,rounding-error,Javascript,Jquery,Biginteger,Rounding Error,如何确定JavaScript中的数字是否太大(如果执行数学运算,将导致舍入错误) 例如,我有一个设置百分比格式的函数。如果它不能正确格式化传入的值,我希望它返回的值与传入的值完全相同 function formatPercent(x, decimals) { var n = parseFloat(x); // Parse (string or number) if ($.isNumeric(n) === false) { re
function formatPercent(x, decimals) {
var n = parseFloat(x); // Parse (string or number)
if ($.isNumeric(n) === false) {
return x; // Return original if not a number
} else {
return n.toFixed(decimals) + '%'; // Return formatted string
}
};
alert(formatPercent(276403573577891842, 2)); // returns 276403573577891840.00%
由于格式化如此巨大的数字是一个绝无仅有的情况,我不希望这样,所以我更希望在传入数字时返回它。舍入误差开始前的限制是什么?我将如何检查它们
更新:
表示精度高达+/-9007199254740992。我正在测试,看看这是否是我需要检查的全部,以安全地失败并返回未修改的传入值
function formatPercent(x, decimals) {
var n = parseFloat(x); // Parse (string or number)
if ($.isNumeric(n) === false) {
return x; // Return original if not a number
} else {
var d = Math.pow(10, decimals)
return (Math.round(n * d) / d).toString() + "%";
}
};
如果小数点为.00,则使用舍入将删除小数点。如果始终以字符串形式传递
x
,则将确保没有舍入错误。问题是在解析数字文本时,276403573577891842
被右舍入,但如果使用字符串,则永远不会发生这种情况。尝试这样做:
function formatPercent(x, decimals) {
if(typeof x != "string" && typeof x != "number") return x;
x = x+"";//convert to string if it is a number
var r = /^(?:(\d+)(\.\d*)?|(\d*)(\.\d+))$/;// RegExp for matching numerical strings
return x.replace(r, function(match, int, dec){
if(decimals>0){
int = (typeof int == "string"?int:"");//if passed string didn't have integers
dec = (typeof dec == "string"?dec:".");//if passed string didn't have decimals
while(dec.length-1<decimals) dec += "0";//pad zeroes until dec.length-1==decimals
return int+dec.slice(0,decimals+1)+"%";//in case dec.length-1>decimals
}
int = (typeof int == "string"?int:"0");//if passed string didn't have integers
return int+"%";
});
// Return formatted string or original string conversion if no match found
}
alert(formatPercent("276403573577891842", 1));// returns 276403573577891842.0%
alert(formatPercent("276403573577891842.55", 1));// returns 276403573577891842.5%
alert(formatPercent("276403573577891842.55", 0));// returns 276403573577891842%
alert(formatPercent(".55", 1));//returns .5%
alert(formatPercent(".55", 0));//returns 0%
alert(formatPercent(276403573577891842, 1));// returns 276403573577891840.0%
alert(formatPercent("this is not a number", 2));// returns this is not a number
alert(formatPercent({key:"not number or string"}, 2));// returns the object as it was
函数格式百分比(x,小数){
if(typeof x!=“string”&&typeof x!=“number”)返回x;
x=x+“”;//如果是数字,则转换为字符串
var r=/^(?:(\d+)(\。\d*)?|(\d*)(\。\d+)$/;//用于匹配数字字符串的RegExp
返回x.replace(r,函数(匹配,int,dec){
如果(小数>0){
int=(typeof int==“string”?int:);//如果传递的字符串没有整数
dec=(typeof dec==“string”?dec:“.”;//如果传递的字符串没有小数
而(12月长度-1分位数)
}
int=(typeof int==“string”?int:“0”);//如果传递的字符串没有整数
返回int+“%”;
});
//如果未找到匹配项,则返回格式化字符串或原始字符串转换
}
警报(formatPercent(“276403573577891842”,1));//返回276403573577891842.0%
警报(formatPercent(“276403573577891842.55”,1));//返回276403573577891842.5%
警报(formatPercent(“276403573577891842.55”,0));//返回276403573577891842%
警报(formatPercent(“.55”,1));//返回0.5%
警报(formatPercent(“.55”,0));//返回0%
警报(formatPercent(276403573577891842,1));//返回276403573577891840.0%
警报(formatPercent(“这不是一个数字”,2));//返回这不是一个数字
警报(formatPercent({key:“非数字或字符串”},2));//按原样返回对象
即使在传递数字的情况下formatPercent仍然失败,这将防止传递的字符串出现舍入错误。请注意,这并不是错误的,因为它失败的唯一情况是将过大的数字硬编码为参数。这是我用来捕获的:
函数getSafeNumber(x){
var n=parseFloat(x);//解析并返回一个浮点数
如果($.isNumeric(n)==false | |
n>=9007199254740992 | |
n由于No的内部表示,不超过9万亿将导致这种类型的错误。这实际上取决于数字的来源,以及您打算如何处理它们。老实说,我没有看到一个应用程序涉及如此大的百分比,那么这到底是为了什么?我正在编写单元测试(QUnit)我也有类似的函数,可以格式化数字(用逗号、小数)来表示印象,点击次数可能会更大…仍然不希望像上面那样是64位整数,但在编写单元测试时,无论如何都能捕捉到它。你链接的文章确实有意义(9007199254740992)。toString(16)=“2000000000”,所以我想只需添加一个if语句,说明它是否高于或等于该值,就可以确定是否信任它的真实值。这是不正确的,因为运行代码会生成“276403573577891840%”,而不是“276403573577891842%”啊,是的,最大整数是2^53每以下。但适用于较小的浮点数。谢谢,+1,因为这确实解决了数学问题。但是,我不想在生产中使用它,因为它相当复杂,正如你在评论中提到的,不需要处理这么大的数字。但是,需要知道何时传入的值太大。我会更新确定我的问题的日期。可能想执行=
…例如:(9007199254740993>9007199254740992)===false
我不确定我是否理解。如果n=9007199254740993
它将按原样返回false。将var n=9007199254740993;n;
放入控制台并查看其内容。它将读取9007199254740992
。
function getSafeNumber(x) {
var n = parseFloat(x); // Parse and return a floating point number
if ($.isNumeric(n) === false ||
n >= 9007199254740992 ||
n <= -9007199254740992) {
return false; // Not numeric or too big or too small
} else {
return n; // return as number
}
};