我知道,关于浮点运算的另一个话题!
我一直试图解决这个问题,但似乎无法想出为什么添加负浮点值对我不起作用。
如果它们都是正值,那么一切都按预期工作(返回的数字并没有超出预期,因为这毕竟是浮点数)。
我使用的是 32 位版本,以防不明显;)
我已经通读了这个:http ://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html 并且在网上找到了各种很好的浮点运算解释——但是,我仍然似乎无法弄清楚如何添加混合的正负值(或下面代码中的情况 2、3 和 4)。
到目前为止,这是我的代码:
int flt32_get_sign (flt32 x) {
/** shift sign bit right; 0 = pos, 1 = neg */
return ((x & 0x80000000) >> 31);
}
int flt32_get_exp (flt32 x) {
/** get biaseed exponent value */
return ((x & 0x7F800000) >> 23);
}
int flt32_get_val (flt32 x) {
/** mask off mantissa
* make sure implicit one set
*/
return ((x & 0x7FFFFF) ^ 0x800000);
}
int flt32_left_most_1 (int bits) {
int position = -1;
/** make sure working with abs value */
if (flt32_get_sign(bits) != 0){
bits = flt32_negate(bits);
}
while(bits != 0){
position++, bits >>=1;
}
return position;
}
int flt32_right_most_1 (int bits) {
int position = -1;
/** make sure working with abs value */
if (flt32_get_sign(bits) != 0){
bits = flt32_negate(bits);
}
while (!(bits & 1)){
position++, bits >>=1;
}
return position;
}
flt32 flt32_abs (flt32 x) {
return (x & 0x7FFFFFFF);
}
flt32 flt32_negate (flt32 x) {
if (flt32_get_sign(x) == 0){
/** is possitive */
return (x ^ 0x80000000);
}
/** else is negative */
return (x & 0x7FFFFFFF);
}
flt32 flt32_add (flt32 x, flt32 y) {
/**
* Possible casses:
* 1: +x +y; 2: +x -y; 3: -x +y; 4: -x -y
*/
flt32 sum, x_val, y_val;
int shift;
/** Case 1 */
if (flt32_get_sign(x) == 0 && flt32_get_sign(y) == 0){
if (flt32_get_exp(x) == flt32_get_exp(y)){
/** no shifting neccesary
* add mantissa's then mask to make sure
* we don't get overflow into the exponent bits
* then add exponent back to new value
*/
sum = (x & 0x7F800000) + ((flt32_get_val(x) + flt32_get_val(y)) & 0x7FFFFF);
} else if (flt32_get_exp(x) > flt32_get_exp(y)){
/** exponent of x is larger than y
* need to right shift y and set its exponent = exponent of x
*/
shift = (flt32_get_exp(x) - flt32_get_exp(y));
y_val = flt32_get_exp(x) + (flt32_get_val(y) >> shift);
sum = x + y_val;
} else {
/** exponent x is smaller than y
* need to right shift x and set its exponent = exponent of y
*/
shift = (flt32_get_exp(y) - flt32_get_exp(x));
x_val = flt32_get_exp(y) + (flt32_get_val(x) >> shift);
sum = x_val + y;
}
}
/** Case 2 */
if (flt32_get_sign(x) == 0 && flt32_get_sign(y) == 1){
if (flt32_get_exp(x) == flt32_get_exp(y)){
/** no shifting neccesary
* add mantissa's then mask to make sure
* we don't get overflow into the exponent bits
* then add exponent back to new value
*/
x_val = ((x & 0xFF800000) + flt32_get_val(x));
y_val = ((y & 0xFF800000) + flt32_get_val(y));
sum = x_val + flt32_negate(y_val);
} else if (flt32_get_exp(x) > flt32_get_exp(y)){
/** exponent of x is larger than y
* need to right shift y and set its exponent = exponent of x
*/
shift = (flt32_get_exp(x) - flt32_get_exp(y));
y_val = flt32_get_exp(x) + (flt32_get_val(y) >> shift);
sum = x + flt32_negate(y_val);
} else {
/** exponent x is smaller than y
* need to right shift x and set its exponent = exponent of y
*/
shift = (flt32_get_exp(y) - flt32_get_exp(x));
x_val = flt32_get_exp(y) + (flt32_get_val(x) >> shift);
sum = x_val + flt32_negate(y);
}
}
return sum;
}
旁白:这只是我在思考所有这些时所做的观察;理解浮点似乎很棒,甚至是必要的——但几乎我遇到的每一篇文章,甚至教科书,都说尽可能避免使用它!:)