正在加载……
专注、离线、切勿分心
问题:计算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 )


posted on 2017-11-30 19:58  正在加载……  阅读(181)  评论(0编辑  收藏  举报