[英]Finding square root without using sqrt function?
我正在寻找无需使用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)
范围内的数字计算平方根。 现在它需要来自<math.h>
frexp()
来获取二进制指数,但是可以通过从IEEE-754数字格式中提取位而不使用frexp()
来获得该指数。
为什么不尝试使用巴比伦方法来找到平方根。
这是我的代码:
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;
}
在查看了之前的答复之后,我希望这将有助于解决任何歧义。 如果先前的解决方案与我的解决方案之间的相似性是虚假的,或者不清楚这种求解根的方法,那么我也制作了一个可以在此处找到的图。
( 出于这个问题,默认值是平方根 )
#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))));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.