计算正实数的乘法逆

我想在不使用除法的情况下计算正实数的乘法逆。 在阅读了Newton Raphson方法的各个页面后,我实现了以下用于计算逆的代码:

#define PRECISION 0.1e-5 double inverse(double num) { double ans = num; while (ans * num > 1 + PRECISION || ans * num < 1 - PRECISION) { ans = ans * (2 - num * ans); } return ans; } 

现在,问题是,我实际上没有得到逆值。 循环无限循环。

所以,我注意到的第一件事是: ans的价值变为负数,我补充说
if (ans < 0) ans *= -1;
所以ans始终是积极的。

第二点需要注意:如果我的初始化为ans = 0.5那么我得到一些num = (1, 2, 3, 5) num值的正确答案。

所以,我的假设是,由于变量ans初始化不合适,实现不起作用。

所以,最后我的问题:
1.这个方法实际上可以用来计算所有正实数的倒数吗?
2.如果是,那么在使用Newton Raphson方法时,假设初始值是否需要任何条件?
3,有没有其他更好的方法来计算倒数而不使用除法?

编辑:

谢谢你的回答。 所以,正如答案中所提到的,我将ans初始值改为PRECISION ,它的确有效! 此外,现在因为初始值对于num特定最大限制是好的,所以ans永远不会变为负数,因此不需要我最初添加的否定检查条件。

所以,这是工作代码(至少适用于我给出的输入。)

 double inverse(double num) { // Added to make it valid for all inputs. // For a too large number under the precision constraint, the answer is 0. if (num > 999999) return 0; double ans = PRECISION; while (ans * num > 1 + PRECISION || ans * num < 1 - PRECISION) { ans = ans * (2 - num * ans); } return ans; } 

您应该从(0,2 / num)中选择初始近似值。 如果从2 / num的另一侧选择它,则该方法可能不会收敛:近似将超过0并且序列将倾向于-∞。

为了达到这个间隔,让我们看看ans*(2-num*ans)改变符号的位置:当2-num * ans <0时,或当ans> 2 / num时,它变为负数。 所以最初ans应小于2 / num。

为了能够选择一个良好的初始近似值,您必须先了解浮点数的表达方式。 通常,计算机使用x = s * m * 2 e ,其中s是符号,m(“尾数”)在(0.5,1)中,e(“指数”)是整数。 现在1 / x = s * 1 / m * 2 -e ,因此问题减少到计算范围(0.5,1)中数字的倒数,并且在该范围内,您可以使用例如1作为初始猜测。 显然,该范围内的最佳初始猜测是48 / 17-32 / 17 * m 。

对于所有数字s * m * 2 e应该起作用的一个初始猜测是s * 2 -e 。 在C中,这可以计算为:

 double ans = num; // Initial guess: ans = 2**(-floor(log num)) long int *t = (long int*)(&ans); *t = (*t & (0x1l<<63)) | (~*t & (0x3FFl << 52)) - (0x1l << 52); /* sign */ /* negative exponent */ 

(注意:我没有检查边缘条件。)

为了近似x的倒数,仅使用乘法和减法,可以猜测数y,然后用2y-xy ^ 2重复地替换y。 一旦y的变化变得(并且保持)足够小,y就是x的倒数的近似值。

ans =(2 * ans) – (num * ans * ans);

请添加parantheses并尝试

在建设性数学中,对于实数x具有倒数,x≠0是不够的。必须给出有理数r,使得0 =>此方法无法扣除所有实数的乘法逆

每个非零元素具有乘法逆的环是一个除环; 同样,它所代表的代数是一个除法代数。

你想用modulo吗? 在模运算中,a的模乘乘逆也被定义:它是数x,使得ax≡1(mod n)。 当且仅当a和n是互质的时,这种乘法逆存在。

_EDIT_ _ ____

刚才注意到,最初ans = num; ans = 2 * ans-num * ans * ans; => ans = 2 * ans – 3 * ans = -1 * ans

所以它总是一个负值。相信初始化为num不是一个好主意。 尝试将ans设置为1