在JavaScript中将Uint8Array转换为Float64Array

4
假设我有一个包含4096个元素的Uint8Array数组,其中每个元素的值都是0xff或255。我想将此数组转换为Float64Array数组,其中前一个数组的8个值对应于一个64位浮点数。 我尝试了以下代码:
 // Every item is 1 byte in pixels array, I want 8 of them to represent
 // a 64-bit float in the float64Array
 let pixels = new Uint8Array([255, 255, 255 ... , 255]); // 4096 values
 let floatArr = new Float64Array(pixels.buffer); // Should be 512 values
 console.log(floatArr); // This shows NaNs all over.

我看到了几个问题似乎与我的问题很接近,但是我无法从提供给它们的答案中得到思路。在检查Mozilla文档后,这似乎是正确使用的方法,但我没有得到预期的结果。我该如何做到这一点?此外,我的限制是浏览器,可以假设是最新版本。

编辑:样本运行的预期结果为:

// pixels array is the input
let pixels = new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); // 16x 0xff, 16 bytes
let floatArr = new Float64Array(pixels.buffer) // I expect this to be
// [0xffffffffffffffff, 0xffffffffffffffff] which is 8bytes x 2,
// Float64Array [ 18446744073709552000, 18446744073709552000 ]

你能添加一个包含8个元素的样例输入和期望输出吗? - ic3b3rg
我已经添加了一个样例输入和期望的输出,希望对您有所帮助。 - Kaan
根据你的预期输出,尝试使用 BigUint64Array - ic3b3rg
2
似乎你的Uint8Array数组中充满了255,无法在32位IEEE 754(js用于表示数字的方式)中表示为Float64。但是,ArrayBuffer中的数据应该仍然存在,就像预期的那样。你为什么要使用Float64Array呢?如果根据变量名称,你正在处理ImageData的数据并且希望执行更快的像素操作,则应坚持使用UInt32Array,每个像素的插槽都更有意义。 - Kaiido
1
你似乎对Float64的二进制表示存在困惑。实际上,你的代码与C++中的uint8_t pixels[] = ...; auto floatArr = reinterpret_cast<double[]>(pixels);等效。 - Patrick Roberts
@Kaiido,我想使用Float64Array,因为我正在进行一次行锤攻击,所以我要在随机像素通道的值中翻转一个位。为了确定它是否可利用(如果它在64位浮点数的前25位中),我想通过将值转换为64位浮点数来检查它。 - Kaan
1个回答

4
请看例如https://en.wikipedia.org/wiki/NaN IEEE 754 NaN使用指数位填充1(与无限大的值相同),并在有效数字中放置一些非零数以使它们不同于无限大的值。此表示允许定义多个不同的NaN值,具体取决于有效数字中设置了哪些位,但还取决于前导符号位的值(但应用程序不需要为这些不同的NaN值提供不同的语义)。
所以基本上你已经创建了一个NaN数组。
要从uint8array缓冲区成功创建一个Float64Array,您需要确保缓冲区包含有效的64位浮点数表示。

// pixels array is the input
let pixels = new Uint8Array([ 174,71,225,122,20,174,40,64]); // Float64Array([12.34]).buffer
let floatArr = new Float64Array(pixels.buffer) // I 
console.log(floatArr) // 12.34

尽管如此,由于颜色像素值的缓冲区转换不太可能创建任何有意义的数字,您可能不想使用Float64Array。(在类似C的东西中,您可能会冒险创建陷阱表示法,不确定JS如何处理这种情况)
在评论中,有人建议使用BigUint64Array可以避免NaN和陷阱表示法。但我认为这仅在Chrome中可用。
正如Kaiido在下面指出的那样,一个Uint32Array将为每个像素保留4个颜色通道,因此除非您尝试对像素进行成对集成,否则您需要的是32位类型数组。

1
我很想点赞,因为第一部分很清晰地指出了问题(如果它们有一个 0, 0, 0, 0, 0, 0, 240, 127 的序列,那么它们就会看到 Infinity);但第二部分让我迷惑了... 一方面,你谈到了选择正确的表示方法的必要性,但紧接着,代码片段展示了一个修改后的数据集,却证明不了什么。你真的建议他们改变他们的数据集吗?附:鉴于变量的名称,我们可以推断它是一个 RGBA 像素值数组,如果通道不重要,那么 Uint32Array 将是最好的表示方法。 - Kaiido
@Kaiido,我会尝试编辑以澄清它。我的观点是指出问题所在,然后提供代码示例,说明成功转换的样子。最后,我试图表达的是,尽管如此,将像素值转换为浮点数组仍然没有太多意义,除非您还进行了归一化或其他操作。我唯一能想到的动机是,如果OP希望跨颜色通道进行位操作,并希望使用float64array作为临时容器。 - visibleman
1
好的,对我来说听起来更好。我个人可能会选择创建一个代码片段,展示如何强制使用其他值,例如其他的NaNInfinity,以证明这一点,也就是反过来的方式,但这可能只是我的想法。 - Kaiido
1
嘿,只是为了澄清一下,我没有进行任何有意义的像素操作。我的行锤攻击是基于GPU的。我尝试检查我的位翻转是否在前25位,以便我可以得出结论它是否可利用。这就是攻击方式:https://www.vusec.net/projects/glitch/。无论如何,你的回答非常有帮助。 - Kaan
@Kaan,你看过那篇论文吗?它是以纯文本形式编写的,为什么你会看到NaN,甚至成为他们的漏洞的一部分:他们搜索存储在252-1范围内应该占据的NaN指针。 - Kaiido
2
@Kaiido,是的,我对与JS相关的一些问题感到困惑,这个答案让我明白了。 - Kaan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接