algorithm - IEEE754 单精度 - 表示数字一半的通用算法
问题描述
假设 N 是根据 IEEE754 单精度标准表示的任意数。我想在 IEEE754 中再次找到 N/2 的最精确表示。
我想找到一个通用算法(用文字描述,我只想考虑必要的步骤和案例)来获得表示。
我的方法是:
说数字表示:b0_b1_b2_b3...b_34
。
- 隔离决定数字符号 (-/+) 的第一位。
- 根据无符号表示计算幂 (p) 的表示
b_1...b_11
。 - 如果
power = 128
我们有特殊情况。如果尾数的所有位都等于 0,则取决于 ,我们有b_0
负无穷大或正无穷大。我们不会改变任何东西。如果尾数至少有一位等于 1,那么我们就有了NaN
价值。我们再一次没有改变。 - 如果
e is inside
]-126, 127[then we have a normalized mantissa
米。新的幂p can be calculated as
p' = p - 1and belongs in the interval
]-127, 126]. We then calculate
m/2` 我们从右边开始表示它并丢失不能包含在尾数的 23 位中的任何位。 - 如果
e = -126
,那么在计算这个数字的一半时,我们传入一个非规格化尾数。我们表示p = 127
,计算尾数的一半,然后从右边开始重新表示它,丢失任何不能包含的信息。 - 最后,如果
e = -127
我们有一个非规范化的尾数。只要m/2
可以用尾数中可用的位数表示而不会丢失信息,我们就表示并保留它p = -127
。在任何其他情况下,我们将数字表示为正或负 0,具体取决于b_0
我错过的任何步骤,可以做出的任何改进(我相信有)或任何看起来完全错误的东西?
解决方案
我在 Java 中实现了除以二的算法,并对所有 32 位输入进行了验证。我试图遵循你的伪代码,但我在三个地方出现了分歧。首先,无穷大/NaN 指数是 128。其次,在情况 4(正常 -> 正常)中,无需对分数进行运算。第三,当您对分数进行运算时,您没有描述半数甚至是如何工作的。否则 LGTM。
public final class FloatDivision {
public static float divideFloatByTwo(float value) {
int bits = Float.floatToIntBits(value);
int sign = bits >>> 31;
int biased_exponent = (bits >>> 23) & 0xff;
int exponent = biased_exponent - 127;
int fraction = bits & 0x7fffff;
if (exponent == 128) {
// value is NaN or infinity
} else if (exponent == -126) {
// value is normal, but result is subnormal
biased_exponent = 0;
fraction = divideNonNegativeIntByTwo(0x800000 | fraction);
} else if (exponent == -127) {
// value is subnormal or zero
fraction = divideNonNegativeIntByTwo(fraction);
} else {
// value and result are normal
biased_exponent--;
}
return Float.intBitsToFloat((sign << 31) | (biased_exponent << 23) | fraction);
}
private static int divideNonNegativeIntByTwo(int value) {
// round half to even
return (value >>> 1) + ((value >>> 1) & value & 1);
}
public static void main(String[] args) {
int bits = Integer.MIN_VALUE;
do {
if (bits % 0x800000 == 0) {
System.out.println(bits);
}
float value = Float.intBitsToFloat(bits);
if (Float.floatToIntBits(divideFloatByTwo(value)) != Float.floatToIntBits(value / 2)) {
System.err.println(bits);
break;
}
} while (++bits != Integer.MIN_VALUE);
}
}
推荐阅读
- android - 如何减少定期工作请求的最小间隔?
- android - FireMonkey:Android 上缺少抗锯齿和抖动效果
- javascript - Vue Composition Api 渲染功能同步发射不起作用
- batch-file - 从不同的驱动器运行批处理脚本
- solid - 如何使用@inrupt/solid-client 模拟容器?
- node.js - 在 AWS WebSocket Gateway Lambda 中如何返回错误?
- html - 如何为连续重叠的三角形编写通用 CSS?
- multidimensional-array - 如何使用自定义步幅创建 ndarray::ArrayView?
- reactjs - findIndex 和 slice 方法如何在 react reducer 函数中工作
- java - 我的活动完成并导航到上一个活动,而没有必要的代码