Javascript float из/в бит
Я пытаюсь выполнить что-то, что является мозгом мертвым простым на любом другом языке, но не javascript: получить бит из float (и наоборот).
В C/С++ это будет что-то вроде
float a = 3.1415;
int b = *((int*)&a);
и наоборот -
int a = 1000;
float b = *((float*)&a);
В С# вы можете использовать битконвертер
... floatBits или что-то подобное на Java... Даже в VB6 ради Христа вы можете memcpy float32 в int32. Как я могу перевести между int и float в javascript?
Ответы
Ответ 1
В JavaScript вы, конечно же, не получите ничего низкого уровня. Было бы чрезвычайно опасно разрешать переработку и рисование указателей на языке, который должен быть безопасен для использования ненадежных веб-сайтов потенциального злоумышленника.
Если вы хотите получить 32-битное представление IEEE754 значения одной точности в Number (помните, что это тоже не int, единственный тип номера, который вы получаете в JavaScript, double
), вам придется сделайте это сами, перебирая значки, экспоненты и битвы мантиссы. Вот пример кода здесь.
Ответ 2
function DoubleToIEEE(f)
{
var buf = new ArrayBuffer(8);
(new Float64Array(buf))[0] = f;
return [ (new Uint32Array(buf))[0] ,(new Uint32Array(buf))[1] ];
}
Ответ 3
function FloatToIEEE(f)
{
var buf = new ArrayBuffer(4);
(new Float32Array(buf))[0] = f;
return (new Uint32Array(buf))[0];
}
К сожалению, это не работает с удвоениями и в старых браузерах.
Ответ 4
- JavaScript использует
double
(IEEE 754) для представления всех номеров
-
double
состоит из полей [знака, экспонента (11 бит), мантиссы (52 бит)].
Значение числа вычисляется по формуле (-1)^sign * (1.mantissa) * 2^(exponent - 1023)
. (1.mantissa
- означает, что мы берем биты мантиссы, добавляем 1 в начале и протачиваем это значение как число, например, если mantissa = 101
получаем число 1.101 (bin) = 1 + 1/2 + 1/8 (dec) = 1.625 (dec)
.
- Мы можем получить значение тестирования бит
sign
, если число больше нуля. Существует небольшая проблема с 0
здесь, потому что double
имеет значения +0
и -0
, но мы можем различать эти два путем вычисления 1/value
и проверки значения +Inf
или -Inf
.
- Так как
1 <= 1.mantissa < 2
мы можем получить значение экспоненты, используя Math.log2
, например. Math.floor(Math.log2(666.0)) = 9
, поэтому показатель exponent - 1023 = 9
и exponent = 1032
, который в двоичном выражении равен (1032).toString(2) = "10000001000"
- После того, как мы получим показатель экспоненты, мы можем масштабировать число до нуля без изменения мантиссы,
value = value / Math.pow(2, Math.floor(Math.log2(666.0)))
, теперь значение представляет число (-1)^sign * (1.mantissa)
. Если мы игнорируем знак и умножаем его на 2^52
, получаем целочисленное значение, имеющее те же самые биты, что и 1.mantissa: ((666 / Math.pow(2, Math.floor(Math.log2(666)))) * Math.pow(2, 52)).toString(2) = "10100110100000000000000000000000000000000000000000000"
(мы должны игнорировать начало 1).
- После некоторой строки concat вы получите то, что хотите.
Это только доказательство концепции, мы не обсуждали денормализованные числа или специальные значения, такие как NaN, но я думаю, что он может быть расширен и для учета этих случаев.
Ответы @bensiu в порядке, но если вы используете какой-то старый интерпретатор JS, вы можете использовать этот подход.
Ответ 5
Как и другие плакаты, JavaScript явно напечатан, поэтому нет различий в типах данных от float до int или наоборот.
Однако, вы ищете
float to int:
Math.floor( 3.9 ); // result: 3 (truncate everything past .) or
Math.round( 3.9 ); // result: 4 (round to nearest whole number)
В зависимости от того, что вы хотите. В C/С++ по существу будет использовать Math.floor
для преобразования в integer из float.
int для float:
var a = 10;
a.toFixed( 3 ); // result: 10.000