I am practicing for my final exam and professor sent us a last year's copy and in it, there is this assignment:
I made a code for it, but it seems it doesn't work properly, it ends up in an endless loop most of the times. This is my code:
int main(){
double x;
double sinx;
int n=1;
int sign=-1;
cin>>x;
sinx=0;
for(;;) {
int fact=1;
for(int i=1;i<=2*n+1;i++){
fact*=i;
}
double term=pow(x,2*n+1)/fact;
if(term==0){
break;
}
sinx += term * sign;
sign *= -1;
n++;
}
cout<<sinx;
}
I really tried everything.
The bug is in integer overflow of fact
. There should be a check that integer overflow hasn't happened.
#include<cassert>
#include<iostream>
#include<cmath>
int main(){
double x;
double sinx;
int n=1;
int sign=-1;
std::cin>>x;
sinx=0;
bool overflow = false;
for(;;) {
int64_t fact=1;
for(int i=1;i<=2*n+1;i++){
old_fact = fact;
fact = fact * i;
// check for overflow
if (fact / i != old_fact) {
overflow = true;
break;
}
}
if (overflow)
break;
double term=std::pow(x,2*n+1)/fact;
if(term==0){
break;
}
std::cout<<"n=" << n << ", fact = " << fact << ", term: " << term <<"\n";
sinx += term * sign;
sign *= -1;
n++;
std::cout<<"sinx=" << sinx<<"\n\n";
}
std::cout<<sinx;
}
godblot link: https://godbolt.org/z/zP8sT6ovq
The problem is with checking if a floating point number is exactly equal to zero.
if(term==0){
This may not ever evaluate to true. It may keep oscillating around a value close to zero. What you could do is to compare if term
is arbitrarily close to zero. You can hard code a value like 0.000001 (which I recommend for a class project) or you can use epsilon if you want to get more technical.
So the code will be like:
if (std::abs(term) < 0.000001) {
break;