Problems finding a number's square root with bisection method - c++

#include<iostream>
#include<cmath>
using namespace std;
double bisection(double errorVal, double userNum){
double upper=userNum, lower=0;
double mid=(lower+upper)/2.0;;
while(mid*mid!=userNum){
double mid=(lower+upper)/2.0;
if(mid*mid>userNum){
upper=mid;
} else {
lower=mid;
}
}
return mid;
}
int main(){
double errorVal=0, userNum=0;
std::cout<<"Please enter a number (larger than 0) to calculate its square root, and the desired margin of error."<<std::endl;
std::cin>>userNum>>errorVal;
bisection(errorVal,userNum);
std::cout<<"The calculated result is "<<bisection(errorVal,userNum)<<". The error is "<<abs(bisection(errorVal,userNum)-sqrt(userNum))<<"."<<std::endl;
}
This is a program I have written to find the square root of any number inputted via the bisection method. I must be doing something wrong here because I am not getting any output once I enter the two input parameters, the process just gets stuck there.
I would also like to know how to properly implement errorVal, as to specify the margin of error allowed. Thanks.

The error value is used to fix any rounding inaccuracies which occur while doing floating point operations.
The following statement would seldom be true, therefor your loop is likely to continue for a long time.
while(mid*mid==userNum)
The usual way to compare two floating points after calculation is
fabs(x1-x2) < e //where, fabs retrieves the absolute value,
//x1,2 are the numbers to compare
//and e is the epsilon chosen.
So, fixing the error value, or commonly referred to as epsilon, would fix the loop as well.
double bisection(double errorVal, double userNum){
double upper=userNum, lower=0;
double mid=(lower+upper)/2.0;
//error val added
//** fabs(mid*mid - userNum) < errorVal is true if the numers are "equal"
//** and you want to run the loop as long as the are NOT "equal"
while(!(fabs(mid*mid - userNum) < errorVal)){
mid=(lower+upper)/2.0;
if(mid*mid>userNum){
upper=mid;
} else {
lower=mid;
}
}
return mid;
}
See:
http://www.cplusplus.com/reference/cmath/fabs/
https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Related

(C++) SQRT function only outputs four decimal places

I'm trying to find the square root of a number through this function and it's not very precise. For example, if you enter 496, my output is 22.2711, while my professor's sample output is 22.271057.
I've tried making an int, double, and long double and the answer stays the same.
I can't use setprecision() either because this code must work for any number, so if the square root is 2 then it needs to print as "2" rather than "2.000000".
Here is the function responsible for finding the square root:
long double myInt::squareRoot() {
long double value = 0.0;
value = sqrtl(static_cast<long double>(num));
return value;
}
Thanks in advance for any help!
example:
#include <cmath>
int main {
int number = 496;
long double result = 0.0;
result = sqrtl(static_cast<long double>(number));
cout << result;
output here is 22.2711.

My program doesn't end

I'm new too c++ and I had to design a program that determines the first four triangular square numbers and the output is exactly how I want it to be, but it wont quit after its printed the first four. I can't figure out what it could be. I can't CTRL C because I will get points taken off. What is the issue here?
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
//Prints name line
cout<<"*********** BY: ********"<<endl;
//Initializing
const int HOW_MANY=4;
int num=1;
int tsn=0;
int z=1;
int x=0;
//How many TSN it will find and be printed
while (x<=HOW_MANY)
{
//
int sum=0;
for (int y=0;y<512;y++)
{
sum+=y;
tsn=pow(num,2);
//Tests if the numbers are TSN
if ((sum==tsn) || (num+1)/sqrt(num)==sqrt(num))
{
//Prints 1-HOW_MANY TSN and what they are
cout<<"Square Triangular Number "<< z <<" is: "<< tsn <<endl;
z++;
x++;
}
}
num++;
}
return 0;
}
If x = 0 then instead of while (x<=HOW_MANY) you need write while (x<HOW_MANY).
x begins at 0. Every time you find and print a number it gets incremented. You'll continue this, so long as x<=HOW_MANY.
You say your program finds 4 numbers but keeps running. After 4 hits, x will be 4. Is 4 <= 4? The answer is yes, so your program keeps running.
Either change the condition to x < HOW_MANY, or initialize x to 1.
EDIT
Did a little leg work, it turns out the sum of all the numbers in the range [1,512] is 131328. The 5th square triangle number is 1413721.
This means after you find the fourth triangle number, you will never sum high enough to find the next one. This will result in the infinite loop you're seeing.
The answer above is still the correct fix, but this is the reason you end up with an infinite loop.
for should be used for iteration and while should be used for condition testing.
The problem, as has been noted, is that your x condition variable is never being incremented to get you out of the outer loop. That's a logic error that can be avoided by using the appropriate control structure for the job.

Arithmetic Error When Converting String to Double

I'm writing a function to convert a user provided string into a double. It works quite well for certain values, but fails for others. For example
string_to_double("123.45") = 123.45
string_to_double(12345) = 12345
but
string_to_double(123.4567) = 123.457
I'm fairly certain that this is some kind of round off error, but I'm not using approximations nor am I using very small or large values. My question is two-fold why am I getting these strange results and how can I change my code to get more accurate results? I'm also doing this as a personal challenge, so suggestions to use methods such as std::stod are not helpful. I believe the problem occurs in the second for-loop, but I felt it was wise to include the entire method because if I missed something it isn't that much extra code to read.
My Code
template <class T>
double numerical_descriptive_measures<T>::string_to_double(std::string user_input)
{
double numeric_value = 0;//Stores numeric value of string. Return value.
int user_input_size = user_input.size();
int power = 0;
/*This loop is for the characteristic portion of the input
once this loop finishes, we know what to multiply the
characterstic portion by(e.g. 1234 = 1*10^3 + 2*10^2 + 3*10^1 + 4)
*/
for(int i = 0;i < user_input_size;i++)
{
if(user_input[i] == '.')
break;
else
power++;
}
/*This loop is for the mantissa. If this portion is zero,
the loop doesn't execute because i will be greater than
user_input_size.*/
for(int i = 0;i < user_input_size;i++)
{
if(user_input[i] != '.')
{
numeric_value += ((double)user_input[i] - 48.0)*pow(10,power-i-1);
}
else
{
double power = -1.0;
for(int j = i+1;j < user_input_size;j++)
{
numeric_value += ((double)user_input[j] - 48.0)*pow(10.0,power);
power = power-1.0;
}
break;
}
}
return numeric_value;
}
The problem is not that you are producing the wrong floating point value, the problem is that you are printing it with insufficient precision:
std::cout<<data<<std::endl
This will only print about six digits of precision. You can use std::setprecision or other methods to print more.
Your code is not producing an incorrect value for "123.4567" but it will produce incorrect values in general. For example, string_to_double("0.0012") produces (on Visual Studio 2015)
0.0012000000000000001117161918529063768801279366016387939453125
but the correct answer is
0.00119999999999999989487575735580549007863737642765045166015625
(You would have to print them to 17 significant digits to tell the difference.)
The problem is that you can't use floating-point to convert to floating-point -- it does not have enough precision in general.
(I've written a lot about this on my site; for example, see http://www.exploringbinary.com/quick-and-dirty-decimal-to-floating-point-conversion/ and http://www.exploringbinary.com/decimal-to-floating-point-needs-arbitrary-precision/ .)

Comparing double error C++

recently I bump into a problem while comparing a double in an if statement. I was trying to cout the number of whole numbers in a double. Being a beginner, I am not sure what gone wrong in my code.
This is my code:
#include <iostream>
using namespace std;
int main(){
int x=0;//convert double to int
long double Out;//Result
long double In=10;//Input double
//Loop Begin
while(In>0){
x=In;//convert double to int
Out= (x/In);//Out(test if whole number, will return 1)
//test for 1
////////////////
if(Out == 1 ){
cout<<"[Whole Number] ";
}
////////////////
//test end
cout<<"In :"<<In<<", ";
cout<<"X :"<<x<<", ";
cout<<"Out :"<<Out<<endl;
In-=0.1;//decrease to finish loop (eventually)
}
//Loop End
cin.get();
return 0;
}
This program will test and output the whole numbers in the double (In). I realized that the accuracy of the double was affecting the if statement which is why I can't get the "[Whole Number]" result. Although I found out that if I used (0.9999) in "if(Out >= 0.9999)" the comparison would work. But I am not sure of a solution, please help! Much appreciated!
Your while loop never stops , its a infinite loop . You are not doing anything with the value of "In" in the while loop hence it will always be greater than 0 ,therefore a infinite loop .
You should probably approach the problem more directly with modf:
double int_part, frac_part;
frac_part = std::modf(in, &int_part);
if (frac_part == 0) {
// int_part contains integer value.
} else {
// process the double non-integer floating point value.
}
Your code works perfectly fine. If you subtract 0.1 from 10.0, then chances are that the result is not an integer due to rounding errors, and your code tells you exactly that. The code isn't wrong, your expectations are wrong.
if (Out >= 0.9999)
is obviously not a solution, because it will always be true if In >= 10000.0.
Do to the way floating point numbers are converted to binary representation by the computer they are inherently inaccurate and thus make logical comparisons somewhat challenging (http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems). When performing such comparisons to floating point numbers you typically will do so utilizing an epsilon constant (http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm) that represents the maximum acceptable error in the comparison. In your case you need to select a suitable value for epsilon (say .000001). Then change your comparison to:
if(abs(out - 1) < epsilon){ //Take the difference between out and 1
cout<<"[Whole Number]"; //If it is "close enough" print to console
}
I am more of a Java guy but I believe you will need #include stdlib.h to utilize the abs() function.
Hope that helps!
Try using the modulus operator: http://www.cprogramming.com/tutorial/modulus.html
Something like if(In % 1 == 0) should work.

c++ Receiving "-1.#IND" from output?

Pretty simple problem here:
When I test the wrong data input I give an error message but -1.#IND comes up after it?
for instance I type a negative where there should be a positive and I get "wrong input dummy-1.#IND"
#include "Header.h"
void error_rep(){
cout<<"Wrong input dummy";
}
double ctok(double c){
double j = c *273.15;
if (j >= -273.15){
return j;
}
else
error_rep();
}
int main(){
double c = 0;
cin >> c;
double k = ctok(c);
cout<<k<<endl;
keep_window_open();
}
What does this mean? and why is it coming up? How do I get rid of it?
What does this mean?
It's Microsoftese for "not a number". It means that k is not a valid floating-point number.
and why is it coming up?
When your range test fails, you don't return a value. This gives undefined behaviour; in practice, it's likely to be equivalent to returning an uninitalised value, which is likely to be garbage. Your compiler should warn you about this, if you have suitable warnings enabled.
How do i get rid of it?
I'd report the error by throwing an exception; then nothing can attempt to use the invalid return value if the function fails. Alternatively, you could return a type with a testable "invalid" state, such as boost::optional<double> or std::pair<double, bool>, and test it before use.
By the way, if that's supposed to be converting degrees Celsius to Kelvin, then you want to add 273.15, not multiply by it; and compare with zero after the conversion (or with 273.15 before converting, if you prefer).
A good compiler with all warning turns on, will have say that an execution path doesn't have a return ...,
double ctok(double c){
double j = c *273.15;
if (j >= -273.15){
return j;
}
else {
error_rep();
///here
throw ;//somthing
}
}
and try-catch exception around ctok call
-1.#IND means that the double value is "negative indefinate NaN". Basically the value stored can't be represented as a number in a double.
See http://blogs.msdn.com/b/oldnewthing/archive/2013/02/21/10395734.aspx