1
votes

I am new to c++ and have written a small program to find out the sine and cosine values of an angle. My sample code is as follows:

#include <math.h>
#include <iostream>
#include <iomanip>
using namespace std;
#define PI 3.14159265

int main ()
{
    double rate, result;
    rate = 90.0;
    result = cos (rate*PI/180);
    cout<<"The cosine of " << rate << " degrees is " << result <<endl;
    return 0;
}

I am getting 1.7949e-009 as the result for cos(90). Is there any way to get 0 as the result (in result variable) instead of this format? same problem is happing for sin 180 degree. I want a general solution of the cases where the resultant value will be 0.

5
Ditch #define PI, use M_PI from the math header.n. 1.8e9-where's-my-share m.
@n.m. it's not a standardized definekrzaq
I would say you PI isn't accurate enough (it has roughly the same precision as the result you get) so try giving it, say, 15 digits of precision and try again.rubenvb
And as a side note: prefer to use cmath instead of math.h when writing c++ code. It's more idiomatic.StoryTeller - Unslander Monica
@krzaq It is standardised by POSIX. Systems that don't conform may respectfully burn in hell.n. 1.8e9-where's-my-share m.

5 Answers

3
votes

Since you tagged the post C++ and not C, let me give you some C++ hints:

  1. The standard header for math is <cmath> and not <math.h>
  2. in c++ there are better way to declare constants that #define
  3. Floating point numbers are not exact representation of real number (for which no computational exact representation can exist), so you always end up with rounding errors.

A more idiomatic way to come to the result cam be this:

#include <cmath>
#include <iostream>
#include <iomanip>

int main ()
{
    const auto PI = std::acos(-1); //let the  computer to find out what PI is

    double rate{}, result{}; //don't let uninitialized values
    rate = 90.0;
    result = std::cos (rate*PI/180);
    std::cout<<"The cosine of " << // set outoput precison for floating point
         std::setprecision(4) << rate << " degrees is " << 
         std::setprecision(4) << result <<endl;
    return 0;
}

Note how I let std:: explicit: C++ <cmath> have more overload for math functions than C.

See:

Note also that, although a more accurate PI makes result to be more accurate, there is always the possibility that the result is not perfect, so -when display floating point values- set the precision to a level that is enough to compensate for commutation errors at a level that makes sense for your problem.

The representation precision of real numbers can be obtained from std::numeric_limits<double>::digits10 (from the <limits> header): it is alway good to cut-out 2-3 digits.

Also, consider rounding errors, when doing subtractions or comparisons: see the example in the std::numeric_limits::epsilon reference doc:

#include <cmath>
#include <limits>
#include <iomanip>
#include <iostream>
#include <type_traits>
#include <algorithm>

template<class T>
typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type
    almost_equal(T x, T y, int ulp)
{
    // the machine epsilon has to be scaled to the magnitude of the values used
    // and multiplied by the desired precision in ULPs (units in the last place)
    return std::abs(x-y) < std::numeric_limits<T>::epsilon() * std::abs(x+y) * ulp
    // unless the result is subnormal
           || std::abs(x-y) < std::numeric_limits<T>::min();
}
int main()
{
    double d1 = 0.2;
    double d2 = 1 / std::sqrt(5) / std::sqrt(5);

    if(d1 == d2)
            std::cout << "d1 == d2\n";
    else
            std::cout << "d1 != d2\n";

    if(almost_equal(d1, d2, 2))
            std::cout << "d1 almost equals d2\n";
    else
            std::cout << "d1 does not almost equal d2\n";
}

which shows how sqrt(5) squared is not ... 5, even if you manage to look so:

(Spoiler: the outpu is

d1 != d2
d1 almost equals d2

) ;-)

1
votes

Is there any way to get 0 as the result [for cosine(90°)]?

Step 1, use a more accurate machine PI

Step 2: Rather than convert to radians and then call cos(), reduce the range and then convert to radians and then call cos().

The range reduction can be done exactly with fmod(x,360.0) and further with various trigonometric identifies.

This answer provide info on the general approach and a detailed sind(double degrees). The following is a general solution of the cases where the resultant value will be 0. This post discusses -0.0 concerns.

// cos()  of 90.0 degrees is   6.1232339957367660e-17
// cosd() of 90.0 degrees is   0.0000000000000000e+00

#include <cmath>


static double d2r(double d) {
  static const auto PI = std::acos(-1);
  return (d / 180.0) * PI;
}

double cosd(double x /* degrees */) {
  if (!isfinite(x)) {
    return std::cos(x);
  }
  int quo;
  double x90 = std::remquo(std::fabs(x), 90.0, &quo);
  double xr = d2r(x90);
  switch (quo % 4) {
    case 0:
      return std::cos(xr);
    case 1:
      // Use + 0.0 to avoid -0.0
      return std::sin(-xr + 0.0);
    case 2:
      return -std::cos(xr);
    case 3:
      return std::sin(xr + 0.0);
  }
  return 0.0;
}
0
votes

I have try M_PI, 3.141592653589793238L or acos(-1l). All of these approximation of PI are not produce exactly 0 in your program. However, at least your can use std::setprecision and std::fixed (in iomanip) to display 0. Or maybe you can use custom epsilon to round the result.

0
votes

the result is 1.7949e-009,this is the scientific way, you can use the fixed way,even specify the precision of point.

In fact 1.7949e-009 is about 0.0000000017949.

the user krzaq specify the output format to be fixed way and set precision 2, it will print :

the cosine of 90.0 degree is 0.00

besides your PI is not accurate enough.

to get high precision, the only extra thing you need to do is to download glm. glm is a outstanding math party, it works excellent in OpenGL math function. here is the code using glm:

#include <iostream>
#include <glm.hpp>

int main()
{
    double Angle, Result;
    Angle  = 90.0;
    Result = glm::cos(glm::radians(Angle));
    std::cout << "The cosine of " << Angle << " degrees is " << std::fixed << Result << std::endl;
    return 0;
}
-1
votes
#include <stdio.h>      
#include <math.h>    

#define PI 3.14159265

int main (){

  double param, result;
  param = 30.0;
  result = sin (param*PI/180);
  printf ("The sine of %f degrees is %f.\n", param, result );
  return 0;
}