我找到了不使用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的值。请为此提供解决方案。
答案 0 :(得分:33)
有一个更好的算法,最多需要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
&gt; sqrt(x)
,然后x/y
&lt; sqrt(x)
大约相同的金额。换句话说,它会很快收敛。
更新:为了加快非常大或非常小的数字的收敛,更改了sqrt()
函数以提取二进制指数并从[1, 4)
范围内的数字计算平方根。它现在需要来自frexp()
的{{1}}来获得二进制指数,但是可以通过从IEEE-754数字格式中提取位而不使用<math.h>
来获得此指数。
答案 1 :(得分:6)
为什么不尝试使用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;
}
祝你好运!
答案 2 :(得分:2)
完全删除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;
}
答案 3 :(得分:1)
如果您需要在不使用sqrt()
的情况下查找平方根,请使用root=pow(x,0.5)
。
其中x是您需要查找其平方根的值。
答案 4 :(得分:1)
正如我发现这个问题已经陈旧并有很多答案,但我有一个简单而有效的答案。
#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;
}
我希望它对未来的用户有所帮助。
答案 5 :(得分:0)
//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;
}
答案 6 :(得分:0)
这是一种非常简单但不安全的方法,用于查找数字的平方根。 不安全,因为它只能通过自然数来运行,你知道基数和指数都是自然数。我不得不将它用于我不允许使用 #include&lt; cmath&gt; -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;
}
答案 7 :(得分:0)
这是一种非常简单的递归方法。
i
0 sussex
答案 8 :(得分:-1)
这是一个非常棒的代码,用于查找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;
}
答案 9 :(得分:-1)
在查看之前的回复后,我希望这有助于解决任何含糊之处。如果以前的解决方案和我的解决方案中的相似之处是虚幻的,或者这种解决根的方法不清楚,我还制作了一个可以找到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))));
}