问题:计算X / n ( X < 65536 * 65536 ,n != 0 )
在计算过程中要保证不会出现除法溢出。
分析:
(1)在计算过程中不会出现除法溢出,也就是说:在计算过程中除法运算的商要小于65535。
设:X / n = ( H * 65536 + L ) / n = ( H / n ) * 65536 + ( L / n )
H = int ( x / 65536 )
L = rem ( x / 65536 )
因为 H < 65536 ,L < 65536 所以
将计算 X / n 转化为计算:( H / n ) * 65536 + ( L / n ) 可以消除溢出的可能性。
两个描述性运算符: int() ;取商
rem() ;取余数
|
(2)将计算 X / n 分解为计算:
( H / n ) * 65536 + ( L / n ) ; H = int ( x / 65536 ) ; L = rem ( x / 65536 )
DIV 指令只能得出余数和商,而我们只保留商(X / n)。余数必然小于除数,一次正确的除法运算只能丢掉一个余数。
我们虽然在具体处理时进行了两次除法运算 ( H / n ) 和 ( L / n ) ;但这实质上是一次除法运算(X / n)问题的分解。也就是说,为保证最终结果的正确,两次除法运算只能丢掉一个余数。
在这个问题中,H / n 产生的余数是绝对不能丢的,因为丢掉了它(设为 r )就相当于丢掉了 r * 65536 。(这是一个相当大的误差)
那么如何处理 ( H / n )产生的余数呢?
|
我们知道:H = int ( H / n) * n + rem ( H / n )
所以有:
( H / n ) * 65536 + ( L / n )
= [ int ( H / n) * n + rem ( H / n ) ] / n * 65536 + L / n
= int ( H / n) * 65536 + rem ( H / n ) * 65536 / n + L / n
= int ( H / n) * 65536 + [ rem ( H / n ) * 65536 + L ] / n
现在讲计算X / n 转化为计算:
int ( H / n) * 65536 + [ rem ( H / n ) * 65536 + L ] / n ;
H = int ( x / 65536 ) ;L = rem ( x / 65536 )
|
在这里要进行两次除法运算:
第一次: H / n (H<65536,所以 H / n 不会溢出)
第二次: [ rem ( H / n ) * 65536 + L ] / n
我们知道第一次不会产生除法溢出。
现证明第二次:
① L ≤ 65535
② rem ( H / n ) ≤ n – 1
由②有:
③ rem ( H / n ) * 65536 ≤ ( n – 1 ) *65536
由①,③有:
④ rem ( H / n ) * 65536 + L ≤ ( n – 1 ) *65536 + 65535
由④有:
⑤ [ rem ( H / n ) * 65536 + L ] / n ≤ [ ( n – 1 ) *65536 + 65535 ] / n
由⑤有:
⑥ [ rem ( H / n ) * 65536 + L ] / n ≤ 65536 – ( 1 / n )
所以 [ rem ( H / n ) * 65536 + L ] / n 不会产生除法溢出。
则:X / n = int ( H / n) * 65536 + [ rem ( H / n ) * 65536 + L ] / n ;
H = int ( x / 65536 ) ;L = rem ( x / 65536 )
|