2013-04-10 1 views
5

私はFloat32Arrayのような型付きの配列にはアクセスできないが、JavaScriptの数値をバイトに変換する必要がある。さて、整数は私がうまく処理することができますが、私は浮動小数点値のためにそれを行う方法がありません。"float"をFloat32Arrayを使わないでJavaScriptのバイトに変換する

私は、浮動小数点数(バイト)を浮動小数点数に変換する問題を解決しましたが、浮動小数点数からバイト数への変換に関するドキュメントはほとんどありません。それを扱う。

理想的には、浮動小数点数を4バイトと8バイトの両方の表現に変換し、どちらを使用するかを選択できます。しかし、単純に数字をとり、8バイトとして吐き出すことができるコードは、おそらくそこそこの32ビットバージョンを思い付くことができるので、素晴らしいものです。

+2

'toString(2)'は役に立ちますか? '(42).toString(2)' – Mohsen

+1

あなたはまた、[ 'Number.toExponential'](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Number/のいくつかの使用を見つけるかもしれません* 'strict'準拠していません* toExponential) –

答えて

7

私は実際にそれを理解したので、私は単精度と倍精度のための私のソリューションを共有します。今では100%標準に準拠しているとは保証できませんが、ループを必要とせず、正常に動作するようです:

単精度(10進値を指定するとバイナリ表現):

function toFloat32(value) { 
    var bytes = 0; 
    switch (value) { 
     case Number.POSITIVE_INFINITY: bytes = 0x7F800000; break; 
     case Number.NEGATIVE_INFINITY: bytes = 0xFF800000; break; 
     case +0.0: bytes = 0x40000000; break; 
     case -0.0: bytes = 0xC0000000; break; 
     default: 
      if (Number.isNaN(value)) { bytes = 0x7FC00000; break; } 

      if (value <= -0.0) { 
       bytes = 0x80000000; 
       value = -value; 
      } 

      var exponent = Math.floor(Math.log(value)/Math.log(2)); 
      var significand = ((value/Math.pow(2, exponent)) * 0x00800000) | 0; 

      exponent += 127; 
      if (exponent >= 0xFF) { 
       exponent = 0xFF; 
       significand = 0; 
      } else if (exponent < 0) exponent = 0; 

      bytes = bytes | (exponent << 23); 
      bytes = bytes | (significand & ~(-1 << 23)); 
     break; 
    } 
    return bytes; 
}; 

倍精度(ビッグエンディアン順におけるバイナリ表現を有する2つの32ビット整数)小数点値出力所与:コピー/ペーストで間違いのため

function toFloat64(value) { 
    if ((byteOffset + 8) > this.byteLength) 
     throw "Invalid byteOffset: Cannot write beyond view boundaries."; 

    var hiWord = 0, loWord = 0; 
    switch (value) { 
     case Number.POSITIVE_INFINITY: hiWord = 0x7FF00000; break; 
     case Number.NEGATIVE_INFINITY: hiWord = 0xFFF00000; break; 
     case +0.0: hiWord = 0x40000000; break; 
     case -0.0: hiWord = 0xC0000000; break; 
     default: 
      if (Number.isNaN(value)) { hiWord = 0x7FF80000; break; } 

      if (value <= -0.0) { 
       hiWord = 0x80000000; 
       value = -value; 
      } 

      var exponent = Math.floor(Math.log(value)/Math.log(2)); 
      var significand = Math.floor((value/Math.pow(2, exponent)) * Math.pow(2, 52)); 

      loWord = significand & 0xFFFFFFFF; 
      significand /= Math.pow(2, 32); 

      exponent += 1023; 
      if (exponent >= 0x7FF) { 
       exponent = 0x7FF; 
       significand = 0; 
      } else if (exponent < 0) exponent = 0; 

      hiWord = hiWord | (exponent << 20); 
      hiWord = hiWord | (significand & ~(-1 << 20)); 
     break; 
    } 

    return [hiWord, loWord]; 
}; 

謝罪、また、コードはエンディアンの処理を排除します。それはかなり簡単に追加することができます。

みんなの投稿提案のおかげで、私はスピードのために可能な限りループ避けたかったように私は、ほとんど自分で考え出すことになりました。

+0

ここには、*見た目に丸みのあるわずかな誤差があります。しかし、それはかなり近いです。よくやった。 – Qix

+0

^私は間違っていた。 64ビットの精度を使用することは素晴らしいことです。 – Qix

1

BinaryParser.encodeFloat hereを参照してください。

+0

このライブラリは' WITH'を使用しています(と私はノー-NOS他のいくつかの確信している)ので、です!使用時には注意してください! – Qix

関連する問題