无浮点指令实现float加法的精度异常问题求助
无浮点指令的浮点数加法实现问题
我需要实现一个不使用浮点指令的浮点数加法函数,尽量用底层操作方便转汇编。目前函数对1.5+2.5、1.5+-1.5、13.6+52.1这类数值计算正确,但计算1000000+0.0001时得到1.4295e+06的错误结果,而1000000+0能得到正确的1e+06,推测是浮点数精度问题。
相关代码如下:
#include <iostream> union FloatBits { float f; uint32_t bits; }; float add_floats(float a, float b) { FloatBits a_bits, b_bits; a_bits.f = a; // Initialize the 32 bit value b_bits.f = b; uint32_t a_sign = a_bits.bits & 0x80000000; // Sign a_sign = a_sign >> 31; uint32_t a_exponent = a_bits.bits & 0x7f800000; // Exponent a_exponent = a_exponent >> 23; uint32_t a_mantissa = a_bits.bits & 0x7fffff; // Mantissa uint32_t b_sign = b_bits.bits & 0x80000000; // Sign b_sign = b_sign >> 31; uint32_t b_exponent = b_bits.bits & 0x7f800000; // Exponent b_exponent = b_exponent >> 23; uint32_t b_mantissa = b_bits.bits & 0x7fffff; // Mantissa std::cout << a_sign << "|" << a_exponent << "|" << a_mantissa << std::endl; std::cout << b_sign << "|" << b_exponent << "|" << b_mantissa << std::endl; if (a == 0 && b == 0) { return 0.0; } else if (a == 0) { return b; } else if (b == 0) { return a; } // Add the implicit 1's a_mantissa |= 0x00800000; b_mantissa |= 0x00800000; // Normalize if (a_exponent < b_exponent) { a_mantissa = a_mantissa >> (b_exponent - a_exponent); a_exponent = b_exponent; } else if (b_exponent < a_exponent) { b_mantissa = b_mantissa >> (a_exponent - b_exponent); b_exponent = a_exponent; } // Else the exponents are equal. uint32_t sign; uint32_t exponent = a_exponent; // the exponents are the same due to normalization uint32_t mantissa; // Add the mantissas if (a_sign == b_sign) { sign = a_sign; mantissa = a_mantissa + b_mantissa; } else { if (a_mantissa > b_mantissa) { sign = a_sign; mantissa = a_mantissa - b_mantissa; } else if (b_mantissa > a_mantissa){ sign = b_sign; mantissa = b_mantissa - a_mantissa; } else if (a_mantissa == b_mantissa) { sign = 0; exponent = 0; mantissa = 0; } } // Handle mantissa overflow if (mantissa >= 0x01000000) { mantissa >>= 1; exponent++; } std::cout << "-------------------------------------------------------" << std::endl; std::cout << sign << "|" << exponent << "|" << mantissa << std::endl; FloatBits result; result.bits = (sign << 31) | (exponent << 23) | (mantissa & 0x007fffff); // std::cout << a << " + " << b << " = " << result.f << std::endl; return result.f; } int main() { float num1, num2; std::cout << "Enter two numbers: "; std::cin >> num1 >> num2; float test = add_floats(num1, num2); std::cout << test; return 0; }
除效率外,代码对多数数值有效,但上述异常情况存在问题。已确认指数归一化逻辑正确,但不确定尾数溢出处理是否恰当,希望得到相关建议。
编辑:发现自己违反了‘不使用浮点指令’的规则,会进行修正,感谢提醒。
更新:已直接改用汇编实现,认为汇编比这种方式更简便。
内容的提问来源于stack exchange,提问作者osy
相关产品推荐
相关产品推荐

