2010-12-10 278 views
19

有沒有什麼辦法可以讀取JS中浮點值的字節?我需要的是將原始FLOAT或DOUBLE值寫入我需要的某種二進制格式,那麼是否有任何方法可以獲得逐字節的IEEE 754表示?當然,寫作也是一樣的問題。在JS中浮點的讀/寫字節

回答

4

請問this snippet有幫助嗎?

@Kevin Gadd

var parser = new BinaryParser 
    ,forty = parser.encodeFloat(40.0,2,8) 
    ,twenty = parser.encodeFloat(20.0,2,8); 
console.log(parser.decodeFloat(forty,2,8).toFixed(1)); //=> 40.0 
console.log(parser.decodeFloat(twenty,2,8).toFixed(1)); //=> 20.0 
+1

+1這很不錯 – Zevan 2010-12-11 02:13:41

+0

非常好!這看起來正是我需要的。 – 2010-12-11 09:19:02

+4

該代碼段中使用的算法被徹底破壞。當用於讀取浮動或雙打時,它會失敗。 例如,它將40.0讀作32.0,將20.0讀作16.0。 – 2012-03-25 10:38:10

0

我希望你能弄清楚(blech),但我假設你問是否有內置的東西。還沒有我聽過的;請參閱the spec的第8.5節和第15.7節。

3

Koolinc的片段是好,如果你需要一個解決方案,強大的,但如果你需要它的有限使用你最好寫你自己的代碼。我寫了下面的功能字節的字符串十六進制表示轉換爲float:

function decodeFloat(data) { 
    var binary = parseInt(data, 16).toString(2); 
    if (binary.length < 32) 
     binary = ('00000000000000000000000000000000'+binary).substr(binary.length); 
    var sign = (binary.charAt(0) == '1')?-1:1; 
    var exponent = parseInt(binary.substr(1, 8), 2) - 127; 
    var significandBase = binary.substr(9); 
    var significandBin = '1'+significandBase; 
    var i = 0; 
    var val = 1; 
    var significand = 0; 

    if (exponent == -127) { 
     if (significandBase.indexOf('1') == -1) 
      return 0; 
     else { 
      exponent = -126; 
      significandBin = '0'+significandBase; 
     } 
    } 

    while (i < significandBin.length) { 
     significand += val * parseInt(significandBin.charAt(i)); 
     val = val/2; 
     i++; 
    } 

    return sign * significand * Math.pow(2, exponent); 
} 

有用來在兩個方向浮動在維基百科上的點的所有格式轉換算法的詳細說明,而且很容易用這些編寫你自己的代碼。從數字轉換爲字節應該更加困難,因爲您需要首先對數字進行歸一化。

+2

我已經擴展了這個解決方案來處理64位浮點數和小端編碼。它還需要一個字節數組而不是base-16字符串(這樣64位浮點數可以正常工作而不會產生舍入問題)。 https://gist.github.com/2192799 – 2012-03-25 10:53:38

35

你可以用typed arrays做到這一點:

var buffer = new ArrayBuffer(4); 
var intView = new Int32Array(buffer); 
var floatView = new Float32Array(buffer); 

floatView[0] = Math.PI 
console.log(intView[0].toString(2)); //bits of the 32 bit float 

或者另一種方式:

var view = new DataView(new ArrayBuffer(4)); 
view.setFloat32(0, Math.PI); 
console.log(view.getInt32(0).toString(2)); //bits of the 32 bit float 

不知道什麼是瀏覽器的支持等等,雖然

+3

Cool,TIL'Double'在JavaScript中被稱爲'Float64'。我正在尋找'DoubleArray' - 無濟於事 - 但是'Float64Array'存在並且對我來說很有用 – 2013-03-01 07:28:37

+1

請注意,這是*不支持的IE9! – Qix 2014-09-17 00:14:42

+1

它看起來像你可以使用'Uint8Array'(至少在Chrome中)而不是'Int32Array'來更容易地得到單獨的字節 – 2017-04-07 19:42:19

6

我創建米洛斯的擴張解決方案,應該有點快,假設TypedArrays當然不是一個選項(在我的情況下,我正在與他們不可用的環境):

function Bytes2Float32(bytes) { 
    var sign = (bytes & 0x80000000) ? -1 : 1; 
    var exponent = ((bytes >> 23) & 0xFF) - 127; 
    var significand = (bytes & ~(-1 << 23)); 

    if (exponent == 128) 
     return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY); 

    if (exponent == -127) { 
     if (significand == 0) return sign * 0.0; 
     exponent = -126; 
     significand /= (1 << 22); 
    } else significand = (significand | (1 << 23))/(1 << 23); 

    return sign * significand * Math.pow(2, exponent); 
} 

給定一個包含4個字節的整數,包含一個IEEE-754 32位單精度浮點數,這將產生(大致)正確的Javascript數值而不使用任何循環。

+1

'if(significantand == 0)return sign * 0.0;' - 肯定任何時間爲零的是......零? 「-1 * 0.0」是否產生負零? – Nick 2013-10-22 22:13:38

+0

@Nick:是的,它確實 – Eric 2014-11-22 10:04:46

+0

@Haravikk,獲取數字的位表示法怎麼樣? – Pacerier 2017-04-17 18:39:16

1

我有一個類似的問題,我想將任何javascript數字轉換爲一個緩衝區,然後解析它,而不會將其字符串化。

function numberToBuffer(num) { 
    const buf = new Buffer(8) 
    buf.writeDoubleLE(num, 0) 
    return buf 
} 

使用例如:

// convert a number to buffer 
const buf = numberToBuffer(3.14) 
// and then from a Buffer 
buf.readDoubleLE(0) === 3.14 

這適用於當前節點LTS(4.3.1)及以上。沒有在較低版本中測試。

+0

我可以證實,這也適用於Node.js 0.10.40。使用舊版本的Node-RED(0.11.1),我顯然無法訪問Float32Array,所以您的解決方案對我來說是唯一的解決方案! 我使用'新的緩衝區(陣列)'從4字節的二進制浮點數組和buffer.readFloatBE(0)來創建緩衝區來檢索浮點數。 – winne2 2017-01-06 16:47:06