Below is a simple program which computes sqrt of a number using Bisection. While executing this with a call like sqrtr(4,1,4) in goes into an endless recursion . I am unable to figure out why this is happening. Below is the function :
double sqrtr(double N , double Low ,double High )
{
double value = 0.00;
double mid = (Low + High + 1)/2;
if(Low == High)
{
value = High;
}
else if (N < mid * mid )
{
value = sqrtr(N,Low,mid-1) ;
}
else if(N >= mid * mid)
{
value = sqrtr(N,mid,High) ;
}
return value;
}
You may have to put a range on your low == high comparison, i.e. high - low < .000001 for six decimal places of precision.
Apart from having a bad termination condition, how did you get this:
else if (N < mid * mid )
{
value = sqrtr(N,Low,mid-1) ;
How is the mid-1 justified? Didn't you cut-and-paste some code for integer binary search?
It's rarely a good idea to rely on floating point values equaling one another. It's very easy for them to be off by a slight amount since, unlike integers, they can't represent all values in the range of values that they represent.
So, you'll likely need to do a comparison to a given precision rather than exact equality.
As pointed out in one of the comments above, you should look at the paper "What Every Computer Scientist Should Know About Floating-Point Arithmetic". It's a classic, excellent paper on the nature of floating point numbers.
There are several problems. As noted by jpalecek, it looks as though you've cut-and-pasted a (not very good) binary search routine for an indexed array without understanding how it works. Also, the termination criterion is overly strict.
I suppose this is a learning exercise, because bisection and recursion is a very poor way to solve for sqrt().
The code below works, but it is horribly slow and inaccurate.
#include <iostream>
using namespace std;
double sqrtr(double N , double Low ,double High )
{
// Precondition: Low and High, Low <= High, must be non-negative, and must
// bracket sqrt(N).
const double sqrt_mef = 1e-8; // Approximate square root of machine efficiency
double mid = (Low + High)/2; // No +1
if((High-Low)/(1+mid) < sqrt_mef)
{
return mid;
}
else if (N < mid * mid )
{
return sqrtr(N,Low,mid) ; // No -1
}
else
{
return sqrtr(N,mid,High) ;
}
}
int main()
{
double sqrt_2 = sqrtr(2.0, 0, 2.0);
cout << sqrt_2*sqrt_2 << endl;
getchar();
}
Related
original outdated code:
Write an algorithm that compute the Euler's number until
My professor from Algorithms course gave me the following homework:
Write a C/C++ program that calculates the value of the Euler's number (e) with a given accuracy of eps > 0.
Hint: The number e = 1 + 1/1! +1/2! + ... + 1 / n! + ... = 2.7172 ... can be calculated as the sum of elements of the sequence x_0, x_1, x_2, ..., where x_0 = 1, x_1 = 1+ 1/1 !, x_2 = 1 + 1/1! +1/2 !, ..., the summation continues as long as the condition |x_(i+1) - x_i| >= eps is valid.
As he further explained, eps is the precision of the algorithm. For example, the precision could be 1/100 |x_(i + 1) - x_i| = absolute value of ( x_(i+1) - x_i )
Currently, my program looks in the following way:
#include<iostream>
#include<cstdlib>
#include<math.h>
// Euler's number
using namespace std;
double factorial(double n)
{
double result = 1;
for(double i = 1; i <= n; i++)
{
result = result*i;
}
return result;
}
int main()
{
long double euler = 2;
long double counter = 2;
long double epsilon = 1.0/1000;
long double moduloDifference;
do
{
euler+= 1 / factorial(counter);
counter++;
moduloDifference = (euler + 1 / factorial(counter+1) - euler);
} while(moduloDifference >= epsilon);
printf("%.35Lf ", euler );
return 0;
}
Issues:
It seems my epsilon value does not work properly. It is supposed to control the precision. For example, when I wish precision of 5 digits, I initialize it to 1.0/10000, and it outputs 3 digits before they get truncated after 8 (.7180).
When I use long double data type, and epsilon = 1/10000, my epsilon gets the value 0, and my program runs infinitely. Yet, if change the data type from long double to double, it works. Why epsilon becomes 0 when using long double data type?
How can I optimize the algorithm of finding Euler's number? I know, I can rid off the function and calculate the Euler's value on the fly, but after each attempt to do that, I receive other errors.
One problem with computing Euler's constant this way is pretty simple: you're starting with some fairly large numbers, but since the denominator in each term is N!, the amount added by each successive term shrinks very quickly. Using naive summation, you quickly reach a point where the value you're adding is small enough that it no longer affects the sum.
In the specific case of Euler's constant, since the numbers constantly decrease, one way we can deal with them quite a bit better is to compute and store all the terms, then add them up in reverse order.
Another possibility that's more general is to use Kahan's summation algorithm instead. This keeps track of a running error while it's doing the summation, and takes the current error into account as it's adding each successive term.
For example, I've rewritten your code to use Kahan summation to compute to (approximately) the limit of precision of a typical (80-bit) long double:
#include<iostream>
#include<cstdlib>
#include<math.h>
#include <vector>
#include <iomanip>
#include <limits>
// Euler's number
using namespace std;
long double factorial(long double n)
{
long double result = 1.0L;
for(int i = 1; i <= n; i++)
{
result = result*i;
}
return result;
}
template <class InIt>
typename std::iterator_traits<InIt>::value_type accumulate(InIt begin, InIt end) {
typedef typename std::iterator_traits<InIt>::value_type real;
real sum = real();
real running_error = real();
for ( ; begin != end; ++begin) {
real difference = *begin - running_error;
real temp = sum + difference;
running_error = (temp - sum) - difference;
sum = temp;
}
return sum;
}
int main()
{
std::vector<long double> terms;
long double epsilon = 1e-19;
long double i = 0;
double term;
for (int i=0; (term=1.0L/factorial(i)) >= epsilon; i++)
terms.push_back(term);
int width = std::numeric_limits<long double>::digits10;
std::cout << std::setw(width) << std::setprecision(width) << accumulate(terms.begin(), terms.end()) << "\n";
}
Result: 2.71828182845904522
In fairness, I should actually add that I haven't checked what happens with your code using naive summation--it's possible the problem you're seeing is from some other source. On the other hand, this does fit fairly well with a type of situation where Kahan summation stands at least a reasonable chance of improving results.
#include<iostream>
#include<cmath>
#include<iomanip>
#define EPSILON 1.0/10000000
#define AMOUNT 6
using namespace std;
int main() {
long double e = 2.0, e0;
long double factorial = 1;
int counter = 2;
long double moduloDifference;
do {
e0 = e;
factorial *= counter++;
e += 1.0 / factorial;
moduloDifference = fabs(e - e0);
} while (moduloDifference >= EPSILON);
cout << "Wynik:" << endl;
cout << setprecision(AMOUNT) << e << endl;
return 0;
}
This an optimized version that does not have a separate function to calculate the factorial.
Issue 1: I am still not sure how EPSILON manages the precision.
Issue 2: I do not understand the real difference between long double and double. Regarding my code, why long double requires a decimal point (1.0/someNumber), and double doesn't (1/someNumber)
double power(double base, int exponent){
//Just for context, a double is larger than a long long int
//Also method programmed to assume non-decimal, non-negative input for root
double answer = base;
if(exponent == 0){
return 1.0;
}
else if(exponent > 0){
for(int i=1; i<exponent; i++){
answer*=base;
}
return answer;
}
else{//if exponent is negative
for(int i=1; i<exponent*(-1); i++){
answer*=base;
}
return 1/answer;
}
}
double newtonRaphsonRoot(double base, int root){//FOR FIDING ROOTS OF CONSTANT #s
if(base == 1){
return 1.0;
}
//Formula: x1 = x0 - f(x0)/f'(x0)
//--------------------------------
//Also method programmed to assume non-negative integer input for root
double epsilon=0.01;//accuracy
double answer = base;//answer starts off as initial guess and becomes better approximated each iteration
if(base > 1){
answer=base/2;
}
while( answer - ( power(answer,root) - base)/(root*power(answer,root-1) ) > epsilon){
//Formula: x1 = x0 - f(x0)/f'(x0). Continue formula until error is less than epsilon
answer = answer - ( power(answer,root) - base)/(root*power(answer,root-1) );
std::cout<<"Approximation: answer = "<< answer <<"\n";
}
return answer;
}
There is a mathematical algorithm for calculating the nth root of a number x, known as the Newton-Raphson method for approximating roots. I tried to program this algorithm. Long story short it seems I'm getting the right answer but
Problem 1: I'm stuck in the while and I don't know why
Problem 2: The accuracy was supposed to be determined by variable epsilon, but answer always comes out to 5 places after decimal.*
One problem is that to check for epsilon the code should be
while (fabs(error) > epsilon) {
... improve ...
}
you are instead checking the next approximation against epsilon (also without fabs).
The other problem is that output stream uses a fixed number of decimals when printing floating point values, if you want to increase that you need to look for std::setprecision (or just use printf("%.18g\n", x); that is what I personally prefer to do).
Important Edit: The original question was about getting the density of both doubles and fractions. As i get the answer for doubles and not for fractions, I'm changing the topic to close this question. The other half of the original question is here
New question
I want to find the density of doubles between 2 given numbers but I can't think of a good way. So I'm looking for a closed-form expressions doublesIn(a,b). Or some code that does the work in a reasonable time.
With doubles i should use some formula with mantissa and exponent I'm not aware of. I already have a code using nextafter and it's awfully slow close to [-1,1] (below 1e6 is very slow)
.
Any ideas? Thanks in advance! :)
PS: If you want to know, I'm coding some math stuff for myself and I want to find how useful would be to replace double with a fraction (long,long or similar) on certain algorithms (like Gaussian elimination, newton's method for finding roots, etc), and for that I want to have some measures.
In what follows, including the program, I am assuming double is represented by IEEE 754 64-bit binary floating point. That is the most likely case, but not guaranteed by the C++ standard.
You can count doubles in a range in constant time, because you can count unsigned integers in a range in constant time by subtracting the start from the end and adjusting for whether the range is open or closed.
The doubles in a finite non-negative range have bit patterns that form a consecutive sequence of integers. For example, the range [1.0,2.0] contains one double for each integer in the range [0x3ff0_0000_0000_0000, 0x4000_0000_0000_0000].
Finite non-positive ranges of doubles behave the same way except the unsigned bit patterns increase in value as the doubles become more negative.
If your range includes both positive and negative numbers, split it at zero, so that you deal with one non-negative range and another non-positive range.
Most of the complications arise when you want to get the count exactly right. In that case, you need to adjust for whether the range is open or closed, and to count zero exactly once.
For your purpose, being off by one or two in a few hundred million may not matter much.
Here is a simple program that demonstrates the idea. It has received little error checking, so use at your own risk.
#include <iostream>
#include <cmath>
using namespace std;
uint64_t count(double start, double end);
void testit(uint64_t expected, double start, double end) {
cout << hex << "Should be " << expected << ": " << count(start, end)
<< endl;
}
double increment(double data, int count) {
int i;
for (i = 0; i < count; i++) {
data = nextafter(data, INFINITY);
}
return data;
}
double decrement(double data, int count) {
int i;
for (i = 0; i < count; i++) {
data = nextafter(data, -INFINITY);
}
return data;
}
int main() {
testit((uint64_t) 1 << 52, 1.0, 2.0);
testit(5, 3.0, increment(3.0, 5));
testit(2, decrement(0, 1), increment(0, 1));
testit((uint64_t) 1 << 52, -2.0, -1.0);
testit(1, -0.0, increment(0, 1));
testit(10, decrement(0,10), -0.0);
return 0;
}
// Return the bit pattern representing a double as
// a 64-bit unsigned integer.
uint64_t toInteger(double data) {
return *reinterpret_cast<uint64_t *>(&data);
}
// Count the doubles in a range, assuming double
// is IEEE 754 64-bit binary.
// Counts [start,end), including start but excluding end
uint64_t count(double start, double end) {
if (!(isfinite(start) && isfinite(end) && start <= end)) {
// Insert real error handling here
cerr << "error" << endl;
return 0;
}
if (start < 0) {
if (end < 0) {
return count(fabs(end), fabs(start));
} else if (end == 0) {
return count(0, fabs(start));
} else {
return count(start, 0) + count(0, end);
}
}
if (start == -0.0) {
start = 0.0;
}
return toInteger(end) - toInteger(start);
}
I need to write a function that squares numbers for a course assignment. It calculates the square roots of numbers like 16 and 25 but does not accurately calculate the square root of 9.
Below is the code
double mysqrt (double x)
{
double low, high, mid;
This if statement decides creates a range to determine the square root.
if (x >= 0) {
low = 0;
high = x;
}
else {
low = x;
high = 1;
}
This statement calculates the middle value
mid = (high + low)/2.0;
The while loop is used to determine the square root.
while (abs(mid*mid - x) > 0.0001)
{
if (mid * mid > x)
high = mid;
else
low = mid;
mid = (high/2.0) + (low/2.0);
}
return mid;
}
Normally I don't just do someone's homework for them, but i wanted to challenge the idea that convergence should always be detected by comparing the error against a fixed epsilon value.
Keep in mind that the double data type, can only represent values taken from a finite range, so comparing for equivalence between two results can be used to detect convergence, where doing so with arbitrary precision could lead to infinite iteration
Also, a set of possible floating-point values is distributed so that the difference between one value and the next greater is smaller for small values than large values, so if you use an epsilon, it usually isn't appropriate to keep it fixed at some arbitrarily "small" value.
The code below performs the same dumb binary search, but the exit condition tests for a re-visiting of a previous iteration's result, which means that further iteration would just repeatedly cover the same search states forever and that the error is close to the minimum possible.
In this way, epsilon is automatically determined by the double data type itself, along with the input. If you replaced double with some kind of arbitrary-precision class, then you would indeed need to supply an epsilon, otherwise irrational roots might loop until some sort of failure, like an out-of-memory condition.
#include <iostream>
#include <iomanip>
double mysqrt(double x) {
double low, high;
if(x < 1) {
if(x <= 0) return 0;
low = x;
high = 1;
} else {
low = 1;
high = x;
}
for(;;) {
const double mid = (low + high) / 2;
if(high == mid || low == mid) return mid;
if(mid * mid > x) {
high = mid;
} else {
low = mid;
}
}
}
int main() {
std::cout << std::setprecision(14) << mysqrt(3) << '\n';
}
In my program, I am trying to take the find the largest prime factor of the number 600851475143. I have made one for loop that determines all the factors of that number and stores them in a vector array. The problem I am having is that I don't know how to determine if the factor can be square rooted and give a whole number rather than a decimal. My code so far is:
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> factors;
int main()
{
double num = 600851475143;
for (int i=1; i<=num; i++)
{
if (fmod(num,i)==0)
{
factors.push_back(i);
}
}
for (int i=0; i<factors.size(); i++)
{
if (sqrt(factor[i])) // ???
}
}
Can someone show me how to determine whether a number can be square rooted or not through my if statement?
int s = sqrt(factor[i]);
if ((s * s) == factor[i])
As hobbs pointed out in the comments,
Assuming that double is the usual 64-bit IEEE-754 double-precision float, for values less than 2^53 the difference between one double and the next representable double is less than or equal to 1. Above 2^53, the precision is worse than integer.
So if your int is 32 bits you are safe. If you have to deal with numbers bigger than 2^53, you may have some precision errors.
Perfect squares can only end in 0, 1, 4, or 9 in base 16, So for 75% of your inputs (assuming they are uniformly distributed) you can avoid a call to the square root in exchange for some very fast bit twiddling.
int isPerfectSquare(int n)
{
int h = n & 0xF; // h is the last hex "digit"
if (h > 9)
return 0;
// Use lazy evaluation to jump out of the if statement as soon as possible
if (h != 2 && h != 3 && h != 5 && h != 6 && h != 7 && h != 8)
{
int t = (int) floor( sqrt((double) n) + 0.5 );
return t*t == n;
}
return 0;
}
usage:
for ( int i = 0; i < factors.size(); i++) {
if ( isPerfectSquare( factor[ i]))
//...
}
Fastest way to determine if an integer's square root is an integer
The following should work. It takes advantage of integer truncation.
if (int (sqrt(factor[i])) * int (sqrt(factor[i])) == factor[i])
It works because the square root of a non-square number is a decimal. By converting to an integer, you remove the fractional part of the double. Once you square this, it is no longer equal to the original square root.
You also have to take into account the round-off error when comparing to cero. You can use std::round if your compiler supports c++11, if not, you can do it yourself (here)
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> factors;
int main()
{
double num = 600851475143;
for (int i=1; i<=num; i++)
{
if (round(fmod(num,i))==0)
{
factors.push_back(i);
}
}
for (int i=0; i<factors.size(); i++)
{
int s = sqrt(factor[i]);
if ((s * s) == factor[i])
}
}
You are asking the wrong question. Your algorithm is wrong. (Well, not entirely, but if it were to be corrected following the presented idea, it would be quite inefficient.) With your approach, you need also to check for cubes, fifth powers and all other prime powers, recursively. Try to find all factors of 5120=5*2^10 for example.
The much easier way is to remove a factor after it was found by dividing
num=num/i
and only increase i if it is no longer a factor. Then, if the iteration encounters some i=j^2 or i=j^3,... , all factors j, if any, were already removed at an earlier stage, when i had the value j, and accounted for in the factor array.
You could also have mentioned that this is from the Euler project, problem 3. Then you would have, possibly, found the recent discussion "advice on how to make my algorithm faster" where more efficient variants of the factorization algorithm were discussed.
Here is a simple C++ function I wrote for determining whether a number has an integer square root or not:
bool has_sqrtroot(int n)
{
double sqrtroot=sqrt(n);
double flr=floor(sqrtroot);
if(abs(sqrtroot - flr) <= 1e-9)
return true;
return false;
}
As sqrt() function works with floating-point it is better to avoid working with its return value (floating-point calculation occasionally gives the wrong result, because of precision error). Rather you can write a function- isSquareNumber(int n), which will decide if the number is a square number or not and the whole calculation will be done in integer.
bool isSquareNumber(int n){
int l=1, h=n;
while(l<=h){
int m = (l+h) / 2;
if(m*m == n){
return true;
}else if(m*m > n){
h = m-1;
}else{
l = m+1;
}
}
return false;
}
int main()
{
// ......
for (int i=0; i<factors.size(); i++){
if (isSquareNumber(factor[i]) == true){
/// code
}
}
}