我已经阅读了几个链接,讨论在一个浮点数中存储2个或3个浮点数。这是一个例子:
Storing two float values in a single float variable
和另一个:
还有另一个:
decode rgb value to single float without bit-shift in glsl
我见过其他人,但他们都使用相同的原则。如果要对x和y进行编码,则将y乘以某个因子,然后将x添加到其中。这就是从纸上开始,但我不明白它在存储到浮动值时如何工作。浮动值只有7位有效数字。如果添加一个大数字和一个小数字,则小数字会被截断并丢失。精度仅显示大数字的值。
由于每个人似乎都开出相同的方法,我自己尝试了它,它完全按照我的想法行事。当我解码数字时,未乘数的数字变为0.0。它在编码的浮点数中完全丢失了。
以下是我尝试测试的一些MaxScript示例:
cp = 256.0 * 256.0
scaleFac = 16777215
for i = 1 to 20 do (
for j = 1 to 20 do (
x = (i as float / 20.01f) as float;
y = (j as float / 20.01f) as float;
xScaled = x * scaleFac;
yScaled = y * scaleFac;
f = (xScaled + yScaled * cp) as float
print ("x[" + xScaled as string + "] y[" + yScaled as string + "]" + " e[" + f as string + "]")
dy = floor(f / cp)
dx = (f - dy * cp)
print ("x[" + dx as string + "] y[" + dy as string + "]" + " e[" + f as string + "]")
)
)
dx每次都是0.0。任何人都可以对此有所了解吗?注意:无论我是否制作cp = 128,256,512或其他什么都没关系。它仍然给我相同类型的结果。
答案 0 :(得分:3)
此方法适用于存储两个整数。您通过乘以scaleFac
有效地将浮点数转换为大整数,这很好,但最好使用int()
将其显式化。然后,您需要确定两件事:cp
大于您正在使用的最大数字(scaleFac
),cp
的平方小到足以适合没有截断的浮点数(单精度浮点数约为7位)。
答案 1 :(得分:1)
以下是 C 中的工作代码,用于将两个float
打包到一个float
中并解压缩。
您应根据可能的值范围(scaleFactor
)更改cp
和yourBiggestNumber * scaleFactor < cp
参数。这是一场精准的战斗。尝试打印一些结果,为您的案例找到合适的价值。以下示例允许[0 to 1)
范围内的浮点数。
#include <math.h>
/* yourBiggestNumber * scaleFactor < cp */
double scaleFactor = 65530.0;
double cp = 256.0 * 256.0;
/* packs given two floats into one float */
float pack_float(float x, float y) {
int x1 = (int) (x * scaleFactor);
int y1 = (int) (y * scaleFactor);
float f = (y1 * cp) + x1;
return f;
}
/* unpacks given float to two floats */
int unpack_float(float f, float* x, float* y){
double dy = floor(f / cp);
double dx = f - (dy * cp);
*y = (float) (dy / scaleFactor);
*x = (float) (dx / scaleFactor);
return 0;
}
答案 2 :(得分:0)
只有当你的个人花车足够小以便装入一个漂浮位置时,它才会起作用。
所以你可以把2个数字“分”成两个来存储2个数字,这些数字可以用一半的空间来表示。
答案 3 :(得分:0)
这是我用于打包和解包浮动的代码。它的工作原理是将第一个浮点数(0..1)打包到8位(0..256)数字的前四个字节中,然后将下一个浮点数打包到剩余的4个位中。得到的数字各有16种可能的组合(2 ^ 4)。在某些情况下,这已经足够了:
private float PackFloatsInto8Bits( float v1, float v2 )
{
var a = Mathf.Round( v1 * 15f );
var b = Mathf.Round( v2 * 15f );
var bitShiftVector = new Vector2( 1f/( 255f/16f ), 1f/255f );
return Vector2.Dot( new Vector2( a, b ), bitShiftVector );
}
private Vector2 UnpackFloatsFrom8Bits( float input )
{
float temp = input * 15.9375f;
float a = Mathf.Floor(temp) / 15.0f;
float b = Frac( temp ) * 1.0667f;
return new Vector2(a, b);
}