如果定数和小数部分分别存储,如何乘以定点数?

时间:2019-10-30 09:29:13

标签: c math addition

我想将两个具有不同小数长度的定点数相乘。 定点部分和小数部分分别存储:

123    . 4
fix    . frac
sint32 . sint32

我使用两个变量,一个用于固定部分,一个用于小数部分。

我尝试使用Karatsuba算法。但这仅适用于固定长度的小数。这两个数字的分数部分是变化的。它们可能是相同的,但是对此没有任何保证。 当然,最大可能值为(2 ^ 32)-1。

将123.4与56.789相乘的最佳方法是什么?

// a = 123.4
signed int a_fxd = 123;
signed int a_frx = 4;
// b = 56.789
signed int b_fxd = 56
signed int b_frc = 789;

1 个答案:

答案 0 :(得分:2)

您需要确定小数部分的实际比例因子是多少。对于您的特定示例,看起来合适的因子可能是1/1000或0.001。这意味着56.789表示为56 + 789×0.001。但这意味着123.4将表示为12 + 400×0.001。也就是说,您输入的问题有误:a_frx为400,而不是4。

我不知道Karatsuba's algorithm,而且我怀疑它真的不适用于此问题。我只知道我在小学赚的钱。

让我们用sc表示比例因子。所以我们的乘法实际上是

( a_fxd + a_frx * sc ) * ( b_fxd + b_frx * sc )

乘以这个,我们得到

a_fxd * b_fxd + a_fxd * b_frx * sc + a_frx * b_fxd * sc + a_frx * b_frx * sc * sc

收集术语,我们有

a_fxd * b_fxd + (a_fxd * b_frx + a_frx * b_fxd + a_frx * b_frx * sc) * sc

因此,如果我们将产品表示为p_fxdp_frx,看起来我们将拥有

p_fxd = a_fxd * b_fxd
p_frx = a_fxd * b_frx + a_frx * b_fxd + a_frx * b_frx * sc

让我们插入实际值:

p_fxd = 123 * 56 = 6888
p_frx = 123 * 789 + 400 * 56 + 400 * 789 * 0.001 = 119762.600

但是还有一个额外的问题,因为实际上p_frx应该是0..999范围内的整数。因此,我们需要丢弃.600并携带119。所以最终结果是

p_fxd = 6888 + 119 = 7007
p_frx = 762

这对应正确的结果123.4×56.789 = 7007.762。

...实际上,正确正确结果为7007.7626,或四舍五入为三位数7007.763。因此严格来说,我们不应该舍弃在p_frx中结束的.600,我们应该四舍五入。

当我们考虑负数的可能性时,可能还会有一些额外的皱纹需要照顾。

最后,可以选择比例因子。实际上,我在这里使用的0.001并不是一个现实的值。对于通用算法,您可能会使用诸如1/10000或1/1000000000或1/32768或1/65536之类的东西。 (使用2的幂表示较大的范围,并且通常可以提高计算效率,但分数部分不那么明显,而十进制表示形式的转换效率较低。例如,如果使用的比例因子为1/32768,{{1} }为13107,而a_frx为25853或25854。)