我发现了不使用sqrt函数找出平方根的算法,然后尝试进入编程。我最终使用C ++中的这个工作代码
#include <iostream>
using namespace std;
double SqrtNumber(double num)
{
double lower_bound=0;
double upper_bound=num;
double temp=0; /* ek edited this line */
int nCount = 50;
while(nCount != 0)
{
temp=(lower_bound+upper_bound)/2;
if(temp*temp==num)
{
return temp;
}
else if(temp*temp > num)
{
upper_bound = temp;
}
else
{
lower_bound = temp;
}
nCount--;
}
return temp;
}
int main()
{
double num;
cout<<"Enter the number\n";
cin>>num;
if(num < 0)
{
cout<<"Error: Negative number!";
return 0;
}
cout<<"Square roots are: +"<<sqrtnum(num) and <<" and -"<<sqrtnum(num);
return 0;
}
现在问题是初始化声明中的迭代次数nCount(这里是50)。例如,为了找出36的平方根,它需要22次迭代,所以没有问题,而找到15625的平方根需要超过50次迭代,所以它会在50次迭代后返回temp的值。请为此提供解决方案。
有一个更好的算法,最多需要6次迭代才能收敛到双倍数的最大精度:
#include <math.h>
double sqrt(double x) {
if (x <= 0)
return 0; // if negative number throw an exception?
int exp = 0;
x = frexp(x, &exp); // extract binary exponent from x
if (exp & 1) { // we want exponent to be even
exp--;
x *= 2;
}
double y = (1+x)/2; // first approximation
double z = 0;
while (y != z) { // yes, we CAN compare doubles here!
z = y;
y = (y + x/y) / 2;
}
return ldexp(y, exp/2); // multiply answer by 2^(exp/2)
}
算法从1开始作为平方根值的第一近似值。然后,在每一步,它通过取当前值y
和x/y
之间的平均值来改进下一近似。如果y
= sqrt(x)
,它将是相同的。如果y
> sqrt(x)
,那么x/y
<sqrt(x)
大约相同的数量。换句话说,它会很快收敛。
更新:为了加速非常大或非常小的数字的收敛,更改sqrt()
函数以提取二进制指数并从[1, 4)
范围中的数字计算平方根。它现在需要来自frexp()
的<math.h>
来获得二进制指数,但是可以通过从IEEE-754数字格式中提取位而不使用frexp()
来获得该指数。
在查看之前的回复之后,我希望这有助于解决任何含糊之处。如果以前的解决方案和我的解决方案中的相似之处是虚幻的,或者这种解决根的方法还不清楚,我还做了一个图表,可以找到here。
(为了这个问题,默认是平方根)
#include <cmath>
// for "pow" function
double sqrt(double A, double root = 2) {
const double e = 2.71828182846;
return pow(e,(pow(10.0,9.0)/root)*(1.0-(pow(A,-pow(10.0,-9.0)))));
}
说明:
这通过泰勒级数,对数性质和一些代数来工作。
举个例子:
log A = N
x
*注意:对于平方根,N = 2;对于任何其他根,您只需要更改一个变量N.
1)更改基数,将基本'x'日志函数转换为自然日志,
log A => ln(A)/ln(x) = N
x
2)重新排列以隔离ln(x),最后只是'x',
ln(A)/N = ln(x)
3)将两边都设为'e'的指数,
e^(ln(A)/N) = e^(ln(x)) >~{ e^ln(x) == x }~> e^(ln(A)/N) = x
4)泰勒系列将“ln”表示为无限级数,
ln(x) = (k=1)Sigma: (1/k)(-1^(k+1))(k-1)^n
<~~~ expanded ~~~>
[(x-1)] - [(1/2)(x-1)^2] + [(1/3)(x-1)^3] - [(1/4)(x-1)^4] + . . .
*注意:继续系列以提高准确性。为简洁起见,在我的函数中使用了10 ^ 9,它表示自然对数的系列收敛,大约7位数,或者千万位数,用于精度,
ln(x) = 10^9(1-x^(-10^(-9)))
5)现在,只需插入此公式即可自然登录到步骤3中获得的简化方程式。
e^[((10^9)/N)(1-A^(-10^-9)] = nth-root of (A)
6)这种实施可能看起来有点过分;然而,它的目的是展示如何在不必猜测和检查的情况下解决根。此外,它将使您能够使用自己的pow函数替换cmath库中的pow函数:
double power(double base, double exponent) {
if (exponent == 0) return 1;
int wholeInt = (int)exponent;
double decimal = exponent - (double)wholeInt;
if (decimal) {
int powerInv = 1/decimal;
if (!wholeInt) return root(base,powerInv);
else return power(root(base,powerInv),wholeInt,true);
}
return power(base, exponent, true);
}
double power(double base, int exponent, bool flag) {
if (exponent < 0) return 1/power(base,-exponent,true);
if (exponent > 0) return base * power(base,exponent-1,true);
else return 1;
}
int root(int A, int root) {
return power(E,(1000000000000/root)*(1-(power(A,-0.000000000001))));
}
为什么不尝试使用Babylonian method来寻找平方根。
这是我的代码:
double sqrt(double number)
{
double error = 0.00001; //define the precision of your result
double s = number;
while ((s - number / s) > error) //loop until precision satisfied
{
s = (s + number / s) / 2;
}
return s;
}
祝好运!
完全删除你的nCount
(因为有一些根源,这个算法将需要多次迭代)。
double SqrtNumber(double num)
{
double lower_bound=0;
double upper_bound=num;
double temp=0;
while(fabs(num - (temp * temp)) > SOME_SMALL_VALUE)
{
temp = (lower_bound+upper_bound)/2;
if (temp*temp >= num)
{
upper_bound = temp;
}
else
{
lower_bound = temp;
}
}
return temp;
}
如果你需要在不使用sqrt()
的情况下找到平方根,请使用root=pow(x,0.5)
。
其中x是您需要找到的平方根的值。
我发现这个问题很老,有很多答案,但我的答案很简单,效果很好..
#define EPSILON 0.0000001 // least minimum value for comparison
double SquareRoot(double _val) {
double low = 0;
double high = _val;
double mid = 0;
while (high - low > EPSILON) {
mid = low + (high - low) / 2; // finding mid value
if (mid*mid > _val) {
high = mid;
} else {
low = mid;
}
}
return mid;
}
我希望它对未来的用户有所帮助。
//long division method.
#include<iostream>
using namespace std;
int main() {
int n, i = 1, divisor, dividend, j = 1, digit;
cin >> n;
while (i * i < n) {
i = i + 1;
}
i = i - 1;
cout << i << '.';
divisor = 2 * i;
dividend = n - (i * i );
while( j <= 5) {
dividend = dividend * 100;
digit = 0;
while ((divisor * 10 + digit) * digit < dividend) {
digit = digit + 1;
}
digit = digit - 1;
cout << digit;
dividend = dividend - ((divisor * 10 + digit) * digit);
divisor = divisor * 10 + 2*digit;
j = j + 1;
}
cout << endl;
return 0;
}
这是一种非常简单但不安全的方法来查找数字的平方根。不安全,因为它只能通过自然数来运行,你知道基数和指数都是自然数。我不得不将它用于我不允许使用#include <cmath> -library的任务,也不允许我使用指针。
效力=基数^指数
// FUNCTION: square-root
int sqrt(int x)
{
int quotient = 0;
int i = 0;
bool resultfound = false;
while (resultfound == false) {
if (i*i == x) {
quotient = i;
resultfound = true;
}
i++;
}
return quotient;
}
这是一种非常简单的递归方法。
double mySqrt(double v, double test) {
if (abs(test * test - v) < 0.0001) {
return test;
}
double highOrLow = v / test;
return mySqrt(v, (test + highOrLow) / 2.0);
}
double mySqrt(double v) {
return mySqrt(v, v/2.0);
}
这是一个非常棒的代码来查找sqrt甚至比原始sqrt函数更快。
float InvSqrt (float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f375a86 - (i>>1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
x = x*(1.5f - xhalf*x*x);
x = x*(1.5f - xhalf*x*x);
x=1/x;
return x;
}