问题描述
|
目前,我正在其中一个应用程序中实现等式“ 0”。
问题是32位值的溢出,我不能使用64位数据类型。
假设当
B = 3
和Y = 805306367
时,它溢出32位值,但当X = -2147483648
时,结果返回到32位范围。
所以我想存储(Y*2^B)
的结果。谁能为此提出一些解决方案。...A和B的值都在-15
到15
之间,而X
,Y
的值可能在2147483647..-2147483648
之间。
输出范围为0...4294967295
。
解决方法
如果数字对于32位变量太大,则可以使用更多位(通过存储更大的变量或使用多个变量),或者放弃精度并将其存储在浮点数中。由于Y可以是MAX_INT,因此根据定义,您不能将其乘以大于1的数字,而仍将其容纳在32位int中。
, 在这种情况下,我将使用循环而不是乘法。像这样:
int newX = X;
int poweredB = ( 1 << B ); // 2^B
for( int i = 0; i < poweredB ; ++i )
{
newX += Y; // or change X directly,if you will not need it later.
}
int result = ( 1 << A ) * newX;
但请注意:这仅在某些情况下有效-仅在您保证此结果不会溢出的情况下。在您的情况下,当Y为大正数而X为大负数(\“大\”-太主观了),这肯定会起作用。但是,如果X为大正数而Y为大正数-将会再次溢出。不仅在这种情况下,而且还有许多其他情况。
, 基于赋值中A和B的值,我认为预期的解决方案将涉及以下内容:
以下内容最好是无符号的,因此请存储X和Y的符号并按其绝对值进行操作
将X和Y分别存储在两个变量中,一个存储高16位,另一个存储低位
就像是
int hiY = Y&0xFFFF0000;
int loY = Y&0x0000FFFF;
向右移动高位部分,以便所有变量都具有高位0
Y *(2 ^ B)实际上是Y向左移动B位。这等效于将高和低部分移位B位,并且由于您已将高部分移位,因此这两个运算都将适合其32位整数
在高处和低处类似地处理X
跟踪X和Y的符号可计算出上下部分的X + Y *(2 ^ B)
再次将高和低结果都移位A位
将高低部分合并为最终结果
, 如果由于本地C不支持64位而不是其他一些压倒性原因而不能使用64位,则可以考虑访问http://gmplib.org/上的GNU多精度算术库。