是否可以在不丢失数据的情况下将24 bit integer
值转换为float
,然后再转换回24 bit integer
?
例如,让我们考虑8位int,一个字节,范围是[-127..127](我们去掉-128)。
public static float ToFloatSample (byte x) { return x / 127f; }
所以,如果是x == -127
,结果将是-1
,如果x == 127
,结果将为1
。如果是x == 64
,结果将是~0.5
public static int ToIntSample (float x) { return (int) (x * 127f); }
所以现在:
int x = some_number;
float f = ToFloatSample (x);
int y = ToIntSample (f);
是否总是x == y
?使用8位int是的,但如果我使用24位呢?
考虑了你的问题,我现在明白你在问什么了。
我知道你有24个比特,代表一个实数n
,这样-1 <= n <= +1
,你想把它加载到System.Single
的一个实例中,然后再加载回来。
在C/C++中,frexp
和ldexp
函数实际上很容易做到这一点,这里有介绍(我如何提取双精度的尾数),但在.NET中,这是一个更复杂的过程。
C#语言规范(以及.NET)指出,它使用IEEE-7541989格式,这意味着您需要将位转储为整数类型,以便执行逐位逻辑来提取组件。除了System.Double
而不是System.Single
之外,SO上已经提出了这个问题,但将答案转换为使用Single
对读者来说是一个微不足道的练习(从c#中的双精度中提取尾数和指数)。
在您的情况下,您希望将24位尾数值存储在Int32
的低24位中,然后使用该链接问题中的代码从Single
实例中加载并提取它。
范围[-1677721616777216]中的每个整数都可以精确地表示为IEEE 754 32位二进制浮点数。这包括无符号和2的补码24位整数范围。简单的铸造就可以了。
这个范围比你预期的要宽,因为有一个额外的有效位没有存储——它是一个已知不是零的二进制数字。