繁体   English   中英

如何在没有较大中间类型的情况下对整数进行乘法和除法运算?

[英]How can I multiply and divide integers without bigger intermediate types?

当前,我正在用C#开发一些模糊逻辑的东西,并希望以一种通用的方式来实现。 为简单起见,我可以使用floatdoubledecimal来处理间隔[0,1],但是为了提高性能,最好使用整数。 关于对称性的一些想法也导致决定省略无符号的最大值和有符号的整数的最小值。 最低的非遗漏值映射为0,最高的非遗漏值映射为1。忽略的值归一化为下一个非遗漏的值。

现在,我想以以下形式实现一些compund计算:

byte f(byte p1, byte p2, byte p3, byte p4)
{
    return (p1 * p2) / (p3 * p4);
}

其中字节值被解释为上述[0,1]间隔。 这意味着p1 * p2 < p1p1 * p2 < p2与大于1的数字相反,这是无效的,例如2 * 3 = 6 ,但0.1 * 0.2 = 0.02

此外,问题是: p1 * p2p3 * p4可能超出类型byte的范围。 整个公式的结果可能不会超出此范围,但是在一个或两个部分中仍然会发生溢出。 当然,我可以将其转换为ushort ,最后转换为byte ,但是对于ulong ,如果没有进一步的努力,我将没有这种可能性,并且我不想坚持使用32位。 另一方面,如果我return (p1 / p3) * (p2 / p4) ,则会减少类型升级,但可能会遇到0的结果,其中实际结果为非零。

因此,我想到了以某种方式同时逐步“收缩”两个产品,直到得到[0,1]解释的结果。 我不需要精确值,启发式与误差小于3点整数关正确的值就足够了,而对于一个ulong更高的错误肯定会好起来的。

到目前为止,我已经尝试将输入转换为区间[0,1]的decimal / float / double float decimal并进行计算。 但这在性能上完全适得其反。 我读了有关除法算法的文章 ,但是找不到在课堂上见过的除法算法 这是关于使用累加器同时计算商和余数。 我试图通过更正对除法的分解部分进行重构和扩展,但是这种方法会中断,发生不可分割性,并且出现太大的错误。 我还做了一些笔记并手动计算了一些整数示例,试图将其分解,抵消,拆分和进行此类奇特的推导,但没有什么能使算法获得令人满意的结果或步骤。

有没有

  • 表演方式
  • 如上乘/除有符号(和无符号)整数
  • 解释为区间[0,1]
  • 没有类型推广

如果您不小心,将会浪费更多的时间进行常规操作所需的转换。

话虽这么说,一种可能有意义的替代方法是映射包含的0到128之间的值(如果需要更高的精度,则映射0到32768),以便将所有值本质上乘以128存储。

因此,如果您具有(0.5 * 0.75) / (0.125 * 0.25) ,则每个数字的存储值分别为64、96、16和32。 如果使用ushort进行这些计算,则将具有(64 * 96) / (16 * 32) = 6144 / 512 = 12 这将12 / 128 = 0.09375

顺便说一下,您可以忽略加,减和除的缩放比例。 对于乘法,您将照常进行乘法,然后除以128。因此,对于0.5 * 0.75您将拥有64 * 96 / 128 = 48 ,与预期的48 / 128 = 0.375相对应。

可以针对平台优化代码,尤其是在平台数量较少时效率更高的情况下。 如有必要,可以将四舍五入添加到操作中。

顺便说一下,如果缩放为2的幂,则可以使用位移进行缩放。 您可能更喜欢使用256而不是128,特别是如果您没有一个循环的位移位,但是您需要更大的宽度来处理某些操作时。

但是,例如,如果未设置最高有效位,则可以进行一些优化,以便仅在必要时使用更大的宽度。

概括回答您的问题:否。
您需要明确说明(和排名)总体目标(例如, 对称性能重要还是重要?)。 简洁地在问题中说明问题,可能会得到有用的答案。
虽然我认为Phil1970的运算法则you can ignore scaling for … division过于乐观的you can ignore scaling for … division运算,但乘法就足够了:如果您生成的部分结果不如“基本类型”大(两倍大),那么您就不得不将乘法部分操作数并将结果拼接在一起。
有关将“更大”的结果拼接在一起的想法: AVR的分数乘法
关于…in signed integers. The lowest, non-omitted value maps to 0… …in signed integers. The lowest, non-omitted value maps to 0… ,我希望您会发现,例如-32767/32768编码的多余分数甚至比二进制补码更难处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM