根据ECMAScript specification,Javascript编号值对应于双精度64位二进制格式IEEE 754值。
对于我目前正在研究的WebIDL验证器,我需要能够确定给定的数值是否可以转换为WebIDL float类型,即它是否可以表示为有限的单精度32位IEEE 754值。
我目前已采用以下方法:
validate: function(value) {
if (typeof value !== 'number' || !Number.isFinite(value)) {
return false;
}
if (value === 0) {
return true;
}
var view = new DataView(new ArrayBuffer(4));
view.setFloat32(0, value);
var converted = view.getFloat32(0);
var relativeError = Math.abs(value - converted) / value;
return relativeError < Number.EPSILON;
}
从本质上讲,我正在做的是:
DataView
包裹ArrayBuffer
。Number
值存储为缓冲区中的32位浮点数。Number.EPSILON
。几条评论:
上述逻辑是否适合我想要实现的目标?这有点矫枉过正吗?是否有更惯用,优雅或高效的方式来做到这一点?
更新
我在此期间发现上述方法不正确。对于1.001
,3.14159
等广泛的值,它将失败。另一方面,将epsilon值更改为机器epsilon的32位浮点数(2 -23 )过于宽松,允许使用16777217
等值。
仍在寻找一个好的解决方案,但目前使用下面的函数来检查整数的上限和下限(2 24 和 - (2 24 ))
validate: function(value) {
return typeof value === 'number' && Number.isFinite(value)
&& value >= -16777216 && value <= 16777216;
}
答案 0 :(得分:3)
当您使用ECMAScript 6时,您可以使用Math.fround
检查它是否是单精度数字:
function isfloat32(x) {
return isNaN(x) || x == Math.fround(x);
}
更新:我错过了关于WebIDL float有限(即不是Inf或NaN)的部分。在那种情况下,
function isfloat32(x) {
return isFinite(x) && x == Math.fround(x);
}