According to the ECMAScript specification , Javascript number values correspond a to double-precision 64-bit binary format IEEE 754 value.
For a WebIDL validator I'm currently working on, I need to be able to figure out if a given number value can be converted to a WebIDL float type, ie if it can be represented as a finite single precision 32-bit IEEE 754 value.
I've currently settled on the following approach:
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;
}
In essence, what I'm doing is:
DataView
around a 4 byte ArrayBuffer
. Number
value as a 32 bit float in the buffer. Number.EPSILON
. A couple of comments:
Is the above logic sound for what I'm trying to achieve? Is it overkill? Is there a more idiomatic, elegant or performant way to do this?
Update
I have in the meantime figured out that the above approach is incorrect. It will fail for a wide range of values such as 1.001
, 3.14159
, and so on. Changing the epsilon value to the machine epsilon for 32-bit floats (2 −23 ) is on the other hand too permissive and allows values like 16777217
.
Still looking for a good solution, but currently going with the function below that just checks the integer upper and lower bounds (2 24 and -(2 24 )).
validate: function(value) {
return typeof value === 'number' && Number.isFinite(value)
&& value >= -16777216 && value <= 16777216;
}
As you're using ECMAScript 6, you can use Math.fround
to check if it's a single-precision number:
function isfloat32(x) {
return isNaN(x) || x == Math.fround(x);
}
UPDATE: I missed the part about a WebIDL float being finite (ie not an Inf or NaN). In that case,
function isfloat32(x) {
return isFinite(x) && x == Math.fround(x);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.