假设N是根据IEEE754单精度标准表示的任意数。我想在IEEE754中再次找到N / 2的最准确的可能表示。
我想找到一个通用算法(用文字描述,我只是想要考虑必要的步骤和案例)来获得表示。
我的方法是:
说出数字代表:b0_b1_b2_b3...b_34
。
b_1...b_11
计算幂(p)的表示。power = 128
我们有特殊情况。如果尾数的所有位都等于0,则取决于b_0
,我们有减号或加无穷大。我们什么都不做改变。如果尾数至少有一位等于1,那么我们有NaN
值。我们再一次改变一切。e is inside
] - 126,127 [then we have a normalized mantissa
m。新的力量p can be calculated as
p' = p - 1 and belongs in the interval
] - 127,126] . We then calculate
m / 2`我们从右边开始表示它并且丢失了无法包含在尾数的23位中的任何位。e = -126
,那么在计算这个数字的一半时,我们会传入一个非规范化的尾数。我们代表p = 127
,计算尾数的一半并从右侧开始再次表示,丢失任何无法包含的信息。e = -127
我们有一个非规范化的尾数。只要m/2
可以用尾数中可用的位数表示而不丢失信息,我们就代表并保留p = -127
。在任何其他情况下,我们根据b_0
我错过的任何步骤,可以做出的任何改进(我确定有)或看似完全错误的任何改进?
答案 0 :(得分:2)
我在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);
}
}