Calculation the Taylor series of sinh
The function calculates the value of sinh(x)
using the following development in a Taylor series:
I want to calculate the value of sinh(3) = 10.01787, but the function outputs 9. I also get this warning:
1>main.c(24): warning C4244: 'function': conversion from 'double' to 'int', possible loss of data
This is my code:
int fattoriale(int n)
{
int risultato = 1;
if (n == 0)
{
return 1;
}
for (int i = 1; i < n + 1; i++)
{
risultato = risultato * i;
}
return risultato;
}
int esponenziale(int base, int esponente)
{
int risultato = 1;
for (int i = 0; i < esponente; i++)
{
risultato = risultato * base;
}
return risultato;
}
double seno_iperbolico(double x)
{
double risultato = 0, check = -1;
for (int n = 0; check != risultato; n++)
{
check = risultato;
risultato = risultato + (((esponenziale(x, ((2 * n) + 1))) / (fattoriale((2 * n) + 1))));
}
return risultato;
}
int main(void)
{
double numero = 1;
double risultato = seno_iperbolico(numero);
}
Please help me fix this program.
It is actually pretty great that the compiler is warning you about this kind of data loss.
You see, when you call this:
esponenziale(x, ((2 * n) + 1))
You essentially lose your accuracy since you are converting your double
, which is x
, to an int
. This is since the signature of esponenziale
is int esponenziale(int base, int esponente)
.
Change it to double esponenziale(double base, int esponente)
, risultato
should be a double
as well, since you are returning it from the function and performing mathematical operations with/on it.
Remember that dividing a double
with an int
gives you a double
back.
Edit: According to ringø's comment, and seeing how it actually solved your issue, you should also set double fattoriale(int n)
and inside that double risultato = 1;
.
You are losing precision since many of the terms will be fractional quantities. Using an int
will clobber the decimal portion. Replace your int
types with double
types as appropriate.
Your factorial function will overflow for surprisingly small values of n
. For 16 bit int
, the largest value of n
is 7, for 32 bit it's 12 and for 64 bit it's 19. The behaviour on overflowing a signed
integral type is undefined. You could use unsigned long long
or a uint128_t
if your compiler supports it. That will buy you a bit more time. But given you're converting to a double
anyway, you may as well use a double
from the get-go. Note that an IEEE764 floating point double will hit infinity at 171!
Be assured that the radius of convergence of the Maclaurin expansion of sinh
is infinite for any value of x
. So any value of x
will work, although convergence might be slow. See http://math.cmu.edu/~bkell/21122-2011f/sinh-maclaurin.pdf.
下一篇: 计算sinh的泰勒级数