将两个浮点值存储在一个浮点变量中

Posted

技术标签:

【中文标题】将两个浮点值存储在一个浮点变量中【英文标题】:Storing two float values in a single float variable 【发布时间】:2013-07-14 10:59:13 【问题描述】:

我想将两个浮点值存储在一个 32 位浮点变量中。编码将在 C# 中进行,而解码将在 HLSL 着色器中完成。

到目前为止,我发现的最佳解决方案是将小数点的偏移量硬连接到编码值中,并将它们存储为“载体”浮点数的整数和小数:

123.456 -> 12.3 and 45.6

它不能处理负值,但没关系。

但是我想知道是否有更好的方法来做到这一点。

编辑:关于任务的更多细节:

我正在使用 Unity 中的固定数据结构,其中顶点数据存储为浮点数。 (Float2 用于 UV,float3 用于法线,等等。)显然没有办法正确添加额外的数据,所以我必须在这些限制内工作,这就是为什么我认为这一切都归结为更普遍的编码数据问题.例如,我可以牺牲辅助 UV 数据来传输 2x2 额外的数据通道。

目标是着色器模型 3.0,但我不介意解码在 SM2.0 上是否也能正常工作。

只要“合理”,数据丢失就可以了。预期值范围是 0..64,但我认为 0..1 也可以,因为重新映射到着色器内的任何范围都很便宜。重要的是保持尽可能高的精度。负值并不重要。

【问题讨论】:

@ZoltanE:你知道你要编码的变量的范围吗? @ZoltanE:还有,你的目标是什么着色器模型和 DirectX 版本?您能否详细说明为什么要这样编码?最后:考虑在gamedev 网站上提问,您可能会得到更好的答案。 也许***.com/questions/4811219/pack-four-bytes-in-a-float这个问题对你有帮助。 【参考方案1】:

按照 Gnietschow 的建议,我调整了 YellPika 的算法。 (它是 Unity 3d 的 C#。)

float Pack(Vector2 input, int precision)

    Vector2 output = input;
    output.x = Mathf.Floor(output.x * (precision - 1));
    output.y = Mathf.Floor(output.y * (precision - 1));

    return (output.x * precision) + output.y;


Vector2 Unpack(float input, int precision)

    Vector2 output = Vector2.zero;

    output.y = input % precision;
    output.x = Mathf.Floor(input / precision);

    return output / (precision - 1);

快速而肮脏的测试产生了以下统计数据(0..1 范围内的 100 万个随机值对):

Precision: 2048 | Avg error: 0.00024424 | Max error: 0.00048852
Precision: 4096 | Avg error: 0.00012208 | Max error: 0.00024417
Precision: 8192 | Avg error: 0.00011035 | Max error: 0.99999940

4096 的精度似乎是最佳选择。请注意,这些测试中的打包和解包都在 CPU 上运行,因此如果 GPU 以浮点精度偷工减料,结果可能会更糟。

无论如何,我不知道这是否是最好的算法,但对于我的情况来说似乎已经足够了。

【讨论】:

您介意解释一下为什么input % precision 部分有效吗?您正在对浮点数和整数进行模数,但模数仅在整数上定义。 定义不限于整数:“模运算求一个数除以另一个数的余数”。问“当我将 7.7 除以 3.3 时余数是多少?”是有道理的? 注意:如果input.y 超过1,则会中断。在那种情况下,+ output.y 只是增加了precision 的值的另一个增量——那么input % precision 只能解压input.y 的小数部分,而它的整数部分(除以precision)被添加到@ 987654332@. 问题:如果像这样将 4 个值打包成两个浮点数,是否可以对这两个浮点数进行插值,然后将插值解包得到源值的近似插值?

以上是关于将两个浮点值存储在一个浮点变量中的主要内容,如果未能解决你的问题,请参考以下文章

如何在NHibernate Criteria Query中截断浮点值?

如何在打开的 cv 中使用向量将一些浮点值存储在 for 循环中

浮点类型是如何存储的

将浮点值存储到无符号字符数组

Elasticsearch:如何将浮点值存储到整型字段中

Elasticsearch:如何将浮点值存储到整型字段中