C++ double rounds up when unwanted - c++

I am writing a program in C++ for the distance formula. The answer to x1=0 y1=0 x2=1 y2=1 should be around 1.14, however the answer printed out is 2.00. Every single variable is stored as double I don't know what is going wrong here. Here is my code, and thank you for any help!!
// main.cpp
// Chap6_42
//
// Created on 10/21/14.
//
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
double distance(double,double,double,double); //distance prototype
int main()
{
double d = 0;
double x1 = 0; //coordinate x1
double x2 = 0; //coord x2
double y1 = 0; //coord y1
double y2 = 0; //coord y2
cout << "Enter four cords (x1,y1,x2,y2) to find the distance between them " << endl;
cout << "x1 = ";
cin >> x1;
cout << "y1 = ";
cin >> y1;
cout << "x2 = ";
cin >> x2;
cout << "y2 = ";
cin >> y2;
d = distance (x2,x1, y2,y1); //calls to distance function, performs computations
cout << "The distance is " << fixed << setprecision(2) << showpoint << d << endl;
return 0;
}
double distance(double x2,double x1,double y2,double y1) //distance function header
{
return sqrt(pow(x2-x1,2.0)) + sqrt(pow(y2-y1,2.0)); //distance function computations
}
//function definition

Your calculation is wrong. You're calling sqrt twice when you should only call it once on the entire sum.
return sqrt(pow(x2-x1,2.0) + pow(y2-y1,2.0));

Your formula is wrong.
You wrote:
sqrt(pow(x2-x1,2.0)) + sqrt(pow(y2-y1,2.0));
It should be:
sqrt(pow(x2-x1,2.0) + pow(y2-y1,2.0));
Anyway, do not use pow there but multiply by hand, that's (probably) faster and more accurate.
sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
Also, often you can use squared distances instead of the distance for a small performance-boost.

Why do you think the answer is around 1.14? Given your example, it should return 2.0
sqrt((pow(2.0 - 1.0, 2.0))) + sqrt((pow(2.0 - 1.0, 2.0)))
sqrt((pow(1.0, 2.0))) + sqrt((pow(1.0, 2.0)))
sqrt(1.0) + sqrt(1.0)
1.0 + 1.0
2.0
Tada!
If you are calculating distance, which the function name implies, you need to adjust your formula.
return sqrt(pow(abs(x2 - x1), 2.0) + pow(abs(y2 - y1), 2.0));

You and pythagorus disagree about how to calculate the distance

Given you intend to use "pow" for some esoteric reason, your code should be
return sqrt(abs(pow(x2-x1,2.0)) + abs(pow(y2-y1,2.0)));
or
return sqrt(pow(x2-x1,int(2)) + pow(y2-y1,int(2)));
If you are going to programming you'll probably need a lot of math. you need to know "on paper" the algorithms you are going to use (even simple ones like the one by Pitagora). Also a rounding error with doubles is not going to change a result so much (unless you are using some bad conditioned algorithm, wich is not the case for Pitagora.

Related

Matlab to C++ Translation

I've recently begun my journey into C++ and have very little knowledge of it other than the basics. I'm trying to translate a Matlab code of mine to C++ as a way to help me understand the differences between the two. The Matlab code takes a given input X(height), and calculates the density (rho), and speed of sound (acousticSpeed) for the input.
Here is the Matlab code.
function [rho, acousticSpeed] = atmos(X)
%only valid to X = 11Km
%Constants
gamma=1.4;
R=287.05;
g=9.81;
To=288.15;
Po=101325;
zo=50;
L=-0.0065;
%Temperature Calculation
T=To+(L*(X-zo));
%Pressure Calculation
P=Po*(T/To)^(-g/(L*R));
%Density Calculation
rho=P/(R*T);
%Acoustic Speed
acousticSpeed=sqrt(gamma*R*T)
end
From what I've learned about C++, functions cannot return more than one value(or at least, its a very intensive process to make it so). This Matlab function returns two values, rho and acousticSpeed. For now, I have split this into 2 functions on C++ to calculate each individual output with the relevant equations.
For Rho I have
rho(double x){
double zo;
double To;
double Po;
double L;
double g;
double R;
double p;
zo = 50;
To = 288.15;
Po = 101325;
L = -0.0065;
g = -9.81;
R = 287.05;
double T = To + L*(x-zo);
double P = pow((Po*(T/To)), -(g*(L*R)));
p = P/(R*T);
return p;
}
For Speed of Sound I have
soundspeed(double x){
double zo;
double To;
double L;
double R;
double as;
double gamma;
zo = 0;
To = 288.15;
L = -0.0065;
R = 287.05;
gamma = 1.4;
double T = To + L*(x-zo);
as = pow(gamma*R*T,0.5);
return as;
}
and my Main function is
int main()
{
cout << "Please enter a desired altitude in meters." << endl;
double x;
double A;
double B;
cin>> x;
A = soundspeed(x);
B = rho(x);
cout << "For Altitude: " << x << " meters" << endl;
cout << "Speed of Sound: " << A << " meters per second." << " Air Density:
" << B;
return 0;
}
For an input of 500 meters, the Speed of Sound is 338 meters per second, and density is approximately 1.225.
The speed of sound function returns the correct value, but the density function returns 0.
I have included iostream and math.h(for the pow() function).
What have I done wrong? Is there a cleaner way to translate this Matlab Function to C++? Are there any other tips for me as a beginner that you experienced folks can give? Thanks.
Apologies for the length, I was unsure how else to include all the information.
The issue was with parenthesis and placement of values, particularly in the pressure calculation.
The original was
double P = pow((Po*(T/To)), -(g*(L*R)));
However the correct equation is
double P = Po*pow((T/To), -(g/(L*R)));
A simple solution that I should have tried before posting, as I did not want to waste anyone's time.
Thank you all for your help!

Cos function giving me zero

I am a complete beginner in programming and I was given the following assignment:
Write a C++ program that computes a pair of estimates of π, using a sequence of inscribed and circumscribed regular polygons. Halt after no more than 30 steps, or when the difference between the perimeters of the circumscribed and inscribed polygons is less than a tolerance of ε=10⁻¹⁵. Your output should have three columns, for the number of sides, the perimeter of an inscribed polygon, and perimeter of the circumscribed polygon. For the last two columns, display 14 digits after the decimal point.
well, I decided to use the law of cos to find the lengths of the sides of the polygon but when I was testing out my program I realized the line:
a = cos(360 / ngon);
keeps giving me a zero as the output which makes everything else also zero and I am not sure what is wrong please help.
P.S. Sorry if the program looks really sloppy, I am really bad at this.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#define _USE_MATH_DEFINES
#include <math.h>
#include <cmath>
using namespace std;
int main()
{
char zzz;
int ngon = 3, a, ak;
double insngon = 0.0;
double cirngon = 0.0;
cout << "Number of Sides" << "\t\t\t" << "Perimeter of insribed region" << "\t\t\t" << "Perimeneter of circumscribed polygon" << "\t\t" << "\n";
while (ngon <= 30)
{
a = cos(360 / ngon);
ak = pow(.5, 2) + pow(.5, 2) - 2 * .5*.5*a;
insngon = (ak*ngon);
cirngon = (ak / (sqrt(1 - pow(ak, 2))));
cout << fixed << setprecision(14) << ngon << " " << insngon << " " << cirngon << endl;
ngon++;
if (cirngon - insngon <= pow(10.0, -15));
cin >> zzz;
return 0;
}
cout << "\nEnter any character and space to end ";
cin >> zzz;
return 0;
}
One issue is that you declared integers, yet you are using them in the call to cos here:
int ngon = 3, a, ak;
//...
a = cos(360 / ngon);
Since a is an integer, the return value of cos (which is of type double) will be truncated. Also, since ngon is an integer, the 360 / ngon will also truncate.
The fix is to make a a double, and divide 360.0 by ngon to prevent the truncation:
int ngon = 3, ak;
double a;
//...
a = cos(360.0 / ngon);
The other issue, as pointed out in the comments is that the trigonometric functions in C++ use radians as the argument, not degrees. You need to change the argument to the equivalent value in radians.
Another issue is that you're using pow to compute values that are constant. There is no need to introduce an unnecessary function call to compute constant values. Just define the constants and use them.
For example:
const double HALF_SQUARED = 0.25
const double EPSILON_VALUE = 10.0e-15;
and then use HALF_SQUARED and EPSILON_VALUE instead of the calls to pow.
Also, pow is itself a floating point function, thus can produce results that are not exact as is discussed by this question . Thus pow(ak, 2) should be replaced with simply ak * ak.
Use float a; (or double a) instead of int a.
Here the return type of a is int
And calculating
a = cos(360/ngon)
Is equivalent to a= cos(120) that is the result of cos(120) is 0.8141 and being a integer type "a" will only store the integer part it.
Therefore 'a' will be 0 and discarding floating value.
Also use double ak; instead of int ak;.
Because here pow function has been used which have return type 'double'

Warning converting to `int' from `double'

Hey this is really one of the first things I've ever coded. I was wondering how might I fix this error. I am currently trying to do some research but can't find anything that is helpful in fixing it.
#include <iostream> // needed for Cin and Cout
#include <cmath>
#include <csmath>
using namespace std;
/************************************
* defines
*************************************/
#define PI 3.14159
/*************************************
* function prototype
*************************************/
int main()
{
//surface and volume
float radius;
float height;
float surfacearea;
float volume;
int pi = 3.14159
//Get the radius
cout << "enter the radius: ";
cin >> (float)radius;
//Get height
cout << "enter height: ";
cin >> height;
//Get the surfacearea
surfacearea = 2(pi*radius^2)+2(pi*radius)* height;
cout << "The surfacearea is: " << surfacearea;
//get volume
volume = (pi*radius)^2*height;
cout << "The volume is: " << volume << endl;
system ("pause");
return 0;
}
Change int to double for pi, because pi is a floating point number, which, as stated in the comments, is C++'s default for floating point numbers. Unless there is a particular reason to use float, use double for floating-point numbers.
double pi = 3.14159;
And the warning will go away.
Also, you don't have to cast your input to float, simply:
cin >> radius;
Additionally, at the very least, change radius^2 to radius*radius.
But better yet, avoid ^ altogether and use std::pow, an example of which can be found here.
Additionally, you don't need to #define PI 3.14159 because you never use it, and you try to define pi in main().
You better declare and initialize local variables right before you need them. For constants like pi you better use const and proper type. For a proper type C++11 offers you a great tool - auto. And ^ does not mean power in C++ you have to use std::pow() instead. So your code should look like this:
const auto pi = 3.14159;
//Get the radius
auto radius = 0.0;
cout << "enter the radius: ";
cin >> radius;
//Get height
auto height = 0.0;
cout << "enter height: ";
cin >> height;
//Get the surfacearea
auto surfacearea = 2 * pi * pow( radius, 2.0 ) + 2 * pi * radius * height;
cout << "The surfacearea is: " << surfacearea << endl;
//get volume
auto volume = pow( pi*radius, 2.0 ) * height;
cout << "The volume is: " << volume << endl;
To begin with, a warning is not an error; if it were a compilation error, then the code would not even compile. However, since it was a warning, that means your code did compile successfully and run, except that it produced a warning about something in your code. Now to the bugs in your code:
Firstly, your declaration for the local variable pi is incorrect. pi is declared in your code as a variable of data type int, short for integer. An integer is only a whole number, positive and negative one, but one that is neve more specific than 10^0. Now the problem is that you are trying to store a decimal value in an int variable. While the compiler is able to make a conversion of the decimal value into an int value, you lose the precision of the value; that's because it rounds the value. If you compile this sample code:
int floating = 1.23456789;
cout << floating << endl;
It will output 1 instead of 1.23456789, with the reason being that an int variable cannot store a float or double value; it however can convert this float or double value into an int value by rounding it.
Therfore, you should change your declaration for pi to:
double pi = 3.14159; // By the way, you forgot to add a semicolon here
Another problem: you are using unnecessary typecating in your cin statement for the radius:
cin >> (float)radius;
You would need to use casting if you want to change the data type of a variable for a particular operation (you don't change the variable data type; you merely process its value as the data type cast. In your case, it is unrequired, because the radius variable is already declared as a data type of float, in the line:
float radius;
Therefore, I would recommend you to simply change this cin statement to:
cin >> radius;
One more thing: the following lines in your code have a problem:
surfacearea = 2(pi*radius^2)+2(pi*radius)* height;
volume = (pi*radius)^2*height;
The "^" symbol does not raise a number to a power; it is called a bitwise XOR operator in c++ and it server the purpose of copying the bit if it is set in one operand but not both. You can find more information about it here: Bitwise Exclusive OR Operator: ^
In c++, if you want to raise a number x to a power like 2, then you have to do x * x. Alternatively, you can use the pow() function like: pow(x, 2.0). For your code, if we use the x*x method, it would be like:
surfacearea = 2(pi*radius*radius)+2(pi*radius)* height;
volume = (pi*radius)*(pi*radius)*height;
Alternatively, if we use the pow() function, then the code would look like:
surfacearea = 2(pi*pow(radius, 2))+2(pi*radius)* height;
volume = pow((pi*radius), 2)*height;
Fixing these peoblems should get your code to work.

for loop help. Terminates when it isnt supposed to. c++

I'm new to stackoverflow, but i did try to look for an answer and could not find it. I also can't seem to figure it out myself. So for a school C++ project, we need to find the area under a curve. I have all the formulas hardcoded in, so don't worry about that. And so the program is supposed to give a higher precision answer with a higher value for (n). But it seems that when I put a value for (n) thats higher than (b), the program just loops a 0 and does not terminate. Could you guys help me please. Thank you. Heres the code:
/* David */
#include <iostream>
using namespace std;
int main()
{
cout << "Please Enter Lower Limit: " << endl;
int a;
cin >> a;
cout << "Please Enter Upper Limit: " << endl;
int b;
cin >> b;
cout << "Please Enter Sub Intervals: " << endl;
int n;
cin >> n;
double Dx = (b - a) / n;
double A = 0;
double X = a;
for (X = a; X <= (b - Dx); X += Dx)
{
A = A + (X*X*Dx);
X = X * Dx;
cout << A << endl;
}
cout << "The area under the curve is: " << A << endl;
return 0;
}
a, b, n are integers. So the following:
(b - a) / n
is probably 0. You can replace it with:
double(b - a) / n
Since all the variables in (b - a) / n are int, you're doing integer division, which discards fractions in the result. Assigning to a double doesn't change this.
You should convert at least one of the variables to double so that you'll get a floating point result with the fractions retained:
double Dx = (b - a) / (double)n;
The other answers are correct. Your problem is probably integer division. You have to cast on of the operands to double.
But you should use static_cast<> instead of C-style casts. Namely use
static_cast<double>(b - a) / n
instead of double(b - a) / n or ((double) (b - a)) / n.
You are performing integer division. Integer division will only return whole numbers by cutting off the decimal:
3/2 == 1 //Because 1.5 will get cut to 1
3/3 == 1
3/4 == 0 //Because 0.5 will get cut to 0
You need to have at least one of the two values on the left or right of the "/" be a decimal type.
3 / 2.0f == 1.5f
3.0f / 2 == 1.5f
3.0f / 2.0f == 1.5f

Nan results when iterating using sin and cos functions

I'm compiling this program using Code::Blocks 10.05 however normally I will get about 10 iterations done before it starts producing Nan in every single output. I was wondering if this is a problem caused by using the cos and sin functions and if there was a decent work around to avoid this?
I have to produce a lot of iterates because I am working on a project for University so it has to be accurate too. I looked up a few articles about how to avoid using sin and cos though I need to follow a few formulas rigorously otherwise the results I produce may be inaccurate so I'm not sure whether to compromise.
struct Particle // Need to define what qualities our particle has
{
double dPosition;
double dAngle;
};
Particle Subject;
void M1(double &x, double &y) //Defines movement if particle doesn't touch inner boundary
{
x = x + 2*y;
}
double d = 0.25; //This can and will be changed when I need to find a distance between
// the two cricles at a later stage
void M2(double &x,double &y, double d) //Defines movement of a particle if it impacts the inner boundary
{
double z = asin(-(sin(y)+d*cos(x + y))/0.35);
double y1 = y;
y = asin(-0.35*sin(z) + d*cos(x + y + 2*z));
x = y + y1 + x + 2*z;
}
int main()
{
cout << "Please tell me where you want this particle to start positions-wise? (Between 0 and 2PI" << endl;
cin >> Subject.dPosition;
cout << "Please tell me the angle that you would like it to make with the normal? (Between 0 and PI/2)" << endl;
cin >> Subject.dAngle;
cout << "How far would you like the distances of the two middle circles to be?" << endl;
double d;
cin >> d;
// These two functions are to understand where the experiment begins from.
// I may add a function to change where the circle starts however I will use radius = 0.35 throughout
cout << "So position is: " << Subject.dPosition << endl;
cout << "And angle with the normal is: " << Subject.dAngle <<endl;
int n=0;
while (n <= 100) //This is used to iterate the process and create an array of Particle data points
{ // in order to use this data to build up Poincare diagrams.
{
while (Subject.dPosition > 2*M_PI)
Subject.dPosition = Subject.dPosition - 2*M_PI;
}
{
if (0.35 >= abs(0.35*cos(Subject.dPosition + Subject.dAngle)+sin(Subject.dAngle))) //This is the condition of hitting the inner boundary
M2(Subject.dPosition, Subject.dAngle, d); //Inner boundary collision
else
M1(Subject.dPosition, Subject.dAngle); // Outer boundary collision
};
cout << "So position is: " << Subject.dPosition << endl;
cout << "And angle with the normal is: " << Subject.dAngle <<endl;
n++;
}
return 0;
}
Nan is shown in c++ as an indication of infinite, zero devision, and some other variations of non representable numbers.
Edit:
As pointed by Matteo Itallia, inf is used for infinite/zero division. I found these approaches:
template<typename T>
inline bool isnan(T value) {
return value != value;
}
// requires #include <limits>
template<typename T>
inline bool isinf(T value) {
return std::numeric_limits<T>::has_infinity &&
value == std::numeric_limits<T>::infinity();
}
Reference: http://bytes.com/topic/c/answers/588254-how-check-double-inf-nan
If the value is outside of [-1,+1] and passed to asin(), the result will be nan
If you need to check for Nan, try the following
if( value != value ){
printf("value is nan\n");
}