I don’t know if I got the corner cases correctly, but anyway here is some code:
function floatToIntBits(f) {
var NAN_BITS = 0|0x7FC00000;
var INF_BITS = 0|0x7F800000;
var ZERO_BITS = 0|0x00000000;
var SIGN_BIT = 0|0x80000000;
var EXP_MASK = 0|0x7F800000;
var MANT_MASK = 0|0x007FFFFF;
if (f != f)
return NAN_BITS;
var signBit = (f > 0.0 || (f == 0.0 && Math.pow(f, -1) > 0)) ? 0 : SIGN_BIT;
var fabs = Math.abs(f);
if (fabs == Number.POSITIVE_INFINITY)
return signBit | INF_BITS;
if (fabs == 0.0)
return signBit | ZERO_BITS;
var e = 0, x = f;
while (x != 0.0) {
e++;
x /= 2.0;
}
var exp = e - (1023 + 52);
if (exp >= 127)
return signBit | INF_BITS;
if (exp <= -126)
return signBit | ZERO_BITS;
var ceil = Math.pow(2.0, exp);
var mantissa = fabs / ceil * Math.pow(2.0, 24);
if (fabs == ceil) {
mantissa = 0;
} else {
exp--;
}
var expBits = ((exp + 127) << 23) & EXP_MASK;
var mantissaBits = mantissa & MANT_MASK;
return signBit | expBits | mantissaBits;
}
function testCase(expected, f) {
var actual = floatToIntBits(f);
if (expected !== actual) {
console.log("expected", expected.toString(16), "actual", actual.toString(16), "f", f);
}
}
testCase(0|0x80000000, -0.0);
testCase(0|0x00000000, 0.0);
testCase(0|0x3F800000, 1.0);
testCase(0|0x42C80000, 100.0);
testCase(0|0x7FC00000, 0.0 / 0.0);
testCase(0|0x7F800000, 1.0 / 0.0);
testCase(0|0xFF800000, 1.0 / -0.0);
0|0x... , JavaScript , , -, 32- . ( ECMAScript, 8.5, .)
: , . , , JavaScript Number. [1.0; 2.0), , IEEE 754-1985 . , IEEE 754-1985 , .
function assert(cond, msg, arg0) {
if (!cond)
console.log("error", msg, arg0);
}
function floatToIntBits(f) {
var NAN_BITS = 0|0x7FC00000;
var INF_BITS = 0|0x7F800000;
var ZERO_BITS = 0|0x00000000;
var SIGN_MASK = 0|0x80000000;
var EXP_MASK = 0|0x7F800000;
var MANT_MASK = 0|0x007FFFFF;
var MANT_MAX = Math.pow(2.0, 23) - 1.0;
if (f != f)
return NAN_BITS;
var hasSign = f < 0.0 || (f == 0.0 && 1.0 / f < 0);
var signBits = hasSign ? SIGN_MASK : 0;
var fabs = Math.abs(f);
if (fabs == Number.POSITIVE_INFINITY)
return signBits | INF_BITS;
var exp = 0, x = fabs;
while (x >= 2.0 && exp <= 127) {
exp++;
x /= 2.0;
}
while (x < 1.0 && exp >= -126) {
exp--;
x *= 2.0;
}
assert(x * Math.pow(2.0, exp) == fabs, "fabs");
var biasedExp = exp + 127;
assert(0 <= biasedExp && biasedExp <= 254, biasedExp);
if (biasedExp == 255)
return signBit | INF_BITS;
if (biasedExp == 0) {
assert(0.0 <= x && x < 2.0, "x in [0.0, 1.0)", x);
var mantissa = x * Math.pow(2.0, 23) / 2.0;
} else {
assert(1.0 <= x && x < 2.0, "x in [0.5; 1.0)", x);
var mantissa = x * Math.pow(2.0, 23) - Math.pow(2.0, 23);
}
assert(0.0 <= mantissa && mantissa <= MANT_MAX, "mantissa in [0.0, 2^23)", mantissa);
var expBits = (biasedExp << 23) & EXP_MASK;
var mantissaBits = mantissa & MANT_MASK;
return signBits | expBits | mantissaBits;
}
function testCase(expected, f) {
var actual = floatToIntBits(f);
if (expected !== actual) {
console.log("error", "number", f, "expected", expected.toString(16), "got", actual.toString(16));
}
}
testCase(0|0xFF800000, 1.0 / -0.0);
testCase(0|0xBF800000, -1.0);
testCase(0|0x80000000, -0.0);
testCase(0|0x00000000, 0.0);
testCase(0|0x00000001, Math.pow(2.0, -(126 + 23)));
testCase(0|0x007FFFFF, Math.pow(2.0, -126) - Math.pow(2.0, -(126 + 23)));
testCase(0|0x00800000, Math.pow(2.0, -126));
testCase(0|0x3F800000, 1.0);
testCase(0|0x42C80000, 100.0);
testCase(0|0x7F800000, 1.0 / 0.0);
testCase(0|0x7FC00000, 0.0 / 0.0);