如何在 C 中表示浮点数的二进制乘法?
How the binary multiplication of floats can be represented in C?
与int的二进制乘法算法可以表示如下:
unsigned int multiply(unsigned int multiplier, unsigned int multiplicand) {
unsigned int product = 0;
while (multiplier != 0) {
if ((multiplier & 1) != 0) {
product = product + multiplicand;
}
multiplier = multiplier >> 1;
multiplicand = multiplicand << 1;
}
return product;
}
此函数执行两个不带运算符“*”的无符号整数的乘法。
但是它不适用于浮点数,因为浮点数由三部分组成:
IEEE 754 single-precision binary floating-point format
这些部分可以隔离如下:
#include <stdio.h>
typedef union {
float f;
struct {
unsigned int mantisa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} float_cast;
int main() {
float_cast d1;
d1.f = 0.15625;
printf("sign = %x\n",d1.parts.sign);
printf("exponent = %x\n",d1.parts.exponent);
printf("mantisa = %x\n",d1.parts.mantisa);
return 0;
}
通过将各部分分隔为整数,我可以操作这些位。但是如何制作一个乘以浮点数部分的函数呢?
提前致谢
- 将尾数乘以整数。
- 加上指数
- 符号异或。
有一些细节。
尾数都应归一化,这意味着 high-order 位为 1 或尾数为 0。为了完全符合要求,您需要处理非范数和其他特殊情况——无穷大、NaN、零——您可能需要归一化、非范数或溢出(设置为无穷大)。
产品在 [1, 4) 范围内,假设值在 [1, 2) 内。如果尾数的乘积大于 2,则需要进行一些修正:将指数递增 1;将两个尾数右移一位。
指数通常以偏移量存储。假设指数的实际值为 e + m,其中 m 是常量偏移量。两个指数表示的和需要减去m,才能得到乘积的指数。
这是我的解决方案和答案:
#include <stdio.h>
float multiplyfloat(float multiplier, float multiplicand) {
typedef union {
float f;
unsigned int i;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
struct {
unsigned int mantissa : 23;
unsigned int b23 : 1;
unsigned int b31_24 : 8;
} parts2;
} float_cast;
float_cast product, f1, f2, m1, m2;
product.f = 0.f;
f1.f = multiplier;
f2.f = multiplicand;
m1 = f1;
m2 = f2;
m1.parts2.b23 = m2.parts2.b23 = 1;
m1.parts2.b31_24 = m2.parts2.b31_24 = 0;
while (m1.parts.mantissa) {
if (m1.parts2.b23) {
product.i += m2.i;
}
m2.i >>= 1;
m1.i <<= 1;
}
if (product.parts.exponent > 1) {
product.parts.mantissa >>= product.parts.exponent - 1;
}
product.parts.exponent += f1.parts.exponent + f2.parts.exponent - 128;
product.parts.sign = f1.parts.sign != f2.parts.sign;
return product.f;
}
int main() {
float a = 134.337368;
float b = 151.23000000001;
float res = multiplyfloat(a, b);
printf("result = %f\n", res);
printf("compare = %f\n", a * b);
system("pause");
return 1;
}
有任何问题,请在下方评论。谢谢
与int的二进制乘法算法可以表示如下:
unsigned int multiply(unsigned int multiplier, unsigned int multiplicand) {
unsigned int product = 0;
while (multiplier != 0) {
if ((multiplier & 1) != 0) {
product = product + multiplicand;
}
multiplier = multiplier >> 1;
multiplicand = multiplicand << 1;
}
return product;
}
此函数执行两个不带运算符“*”的无符号整数的乘法。 但是它不适用于浮点数,因为浮点数由三部分组成:
IEEE 754 single-precision binary floating-point format
这些部分可以隔离如下:
#include <stdio.h>
typedef union {
float f;
struct {
unsigned int mantisa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} float_cast;
int main() {
float_cast d1;
d1.f = 0.15625;
printf("sign = %x\n",d1.parts.sign);
printf("exponent = %x\n",d1.parts.exponent);
printf("mantisa = %x\n",d1.parts.mantisa);
return 0;
}
通过将各部分分隔为整数,我可以操作这些位。但是如何制作一个乘以浮点数部分的函数呢?
提前致谢
- 将尾数乘以整数。
- 加上指数
- 符号异或。
有一些细节。
尾数都应归一化,这意味着 high-order 位为 1 或尾数为 0。为了完全符合要求,您需要处理非范数和其他特殊情况——无穷大、NaN、零——您可能需要归一化、非范数或溢出(设置为无穷大)。
产品在 [1, 4) 范围内,假设值在 [1, 2) 内。如果尾数的乘积大于 2,则需要进行一些修正:将指数递增 1;将两个尾数右移一位。
指数通常以偏移量存储。假设指数的实际值为 e + m,其中 m 是常量偏移量。两个指数表示的和需要减去m,才能得到乘积的指数。
这是我的解决方案和答案:
#include <stdio.h>
float multiplyfloat(float multiplier, float multiplicand) {
typedef union {
float f;
unsigned int i;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
struct {
unsigned int mantissa : 23;
unsigned int b23 : 1;
unsigned int b31_24 : 8;
} parts2;
} float_cast;
float_cast product, f1, f2, m1, m2;
product.f = 0.f;
f1.f = multiplier;
f2.f = multiplicand;
m1 = f1;
m2 = f2;
m1.parts2.b23 = m2.parts2.b23 = 1;
m1.parts2.b31_24 = m2.parts2.b31_24 = 0;
while (m1.parts.mantissa) {
if (m1.parts2.b23) {
product.i += m2.i;
}
m2.i >>= 1;
m1.i <<= 1;
}
if (product.parts.exponent > 1) {
product.parts.mantissa >>= product.parts.exponent - 1;
}
product.parts.exponent += f1.parts.exponent + f2.parts.exponent - 128;
product.parts.sign = f1.parts.sign != f2.parts.sign;
return product.f;
}
int main() {
float a = 134.337368;
float b = 151.23000000001;
float res = multiplyfloat(a, b);
printf("result = %f\n", res);
printf("compare = %f\n", a * b);
system("pause");
return 1;
}
有任何问题,请在下方评论。谢谢