2013-04-10 11 views
5

olmadan Javascript'te "float" değerini baytlara dönüştürün. Tamam, Float32Array gibi yazılan dizilere erişemediğim, ancak yine de Javascript numarasını bayt olarak dönüştürebilen oldukça rahatsız edici bir durumum. . Şimdi, tam olarak ele alabildiğim bir tamsayı, ama kayan nokta değeri için nasıl yapılacağını bilmiyorum.Float32Array

Bunu başka bir şekilde yapmanın sorununu çözdüm (baytları bir floatta), ancak çoğu dil yalnızca işaretçiyi okumanıza veya ortak sınıflar oluşturmanıza izin verdiğinden, floattan bayta dönüştürmeye ilişkin belgeler oldukça azdır. işleniyor.

İdeal olarak, floatların hem 4 baytlık hem de 8 bayt gösterimlerine dönüştürülebilmesini ve hangisinin kullanılacağını seçmek istiyorum. Bununla birlikte, bir sayı alıp 8-bayt olarak tüküren kod yine de harika olurdu çünkü muhtemelen kendimden 32-bit sürümle gelebiliyordum.

+2

'toString (2)' yardımcı olacaktır? (42) .toString (2) ' – Mohsen

+1

Ayrıca, [' Number.toExponential'] 'nin bazı kullanımlarını da bulabilirsiniz (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Number/ toExponential) –

cevap

7

Tamam, ben de bunu çözdüm, böylece çözümümü tek ve çift duyarlık için paylaşacağım. Şimdi% 100 standartlara uygun olduklarını garanti edemiyorum, ancak döngüler gerektirmiyor ve iyi çalışıyor gibi görünüyor:

Tek kesinlik (ondalık değer çıktıları, ikili ile tek bir 32 bitlik büyük bir endian tamsayı verilir) temsilidir):

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; 
}; 

Çift hassasiyetli (büyük-endian sırayla ikili gösterimi ile iki 32-bit tamsayı) bir ondalık değer çıkışları verilen: copy/yapıştırarak alanında herhangi bir hata

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]; 
}; 

Özür dileriz, Ayrıca kod, herhangi bir endianlık ele alır. ugh eklemek oldukça kolaydır.

Öneriler gönderen herkese teşekkürler, ancak hız için mümkün olduğu kadar çok döngüden kaçınmak istediğim için çoğunlukla kendi başıma keşfettim; hala tam anlamıyla hızlı değil ama yapacaklar =)

+0

Burada * hafif bir yuvarlama hatası var gibi görünüyor. Ancak, oldukça darn yakın. İyi iş. – Qix

+0

^Yanılıyordum; 64-bit hassasiyeti kullanarak harika çalışır. – Qix

1

Bkz. BinaryParser.encodeFloat here.

+0

Bu kütüphane 'with' kullanır (ve diğer birkaç no-nos'dur) ve dolayısıyla *' 'strict' uyumlu değildir! Kullanırken dikkatli olun! – Qix