Reputation: 23
I maded some code to compute the sine and cosine, but, the code is not so good, I want to know if is possible to make the code to compute the values with Linq.
that is my code to compute sine
var primes = PrimeNumbers(3, 15);
bool SumSub = false;
decimal seno = (decimal)(nGrau * nSeno);
foreach (var a in primes)
{
if (SumSub == false)
{
seno -= (decimal)Math.Pow(nGrau, (double)a) / Factorial(a);
SumSub = true;
}
else
{
seno += (decimal)Math.Pow(nGrau, (double)a) / Factorial(a);
SumSub = false;
}
}
Console.WriteLine(seno);
Is possible to make a code to compute the sine of degres using linq ?
Upvotes: 2
Views: 294
Reputation: 86718
Here's a function that computes the adds up the first 10 terms of the Taylor series approximation of cosine:
var theta = 1.0m; // angle in radians
Enumerable.Range(1, 10).Aggregate(
new { term = 1.0m, accum = 0.0m },
(state, n) => new {
term = -state.term * theta * theta / (2 * n - 1) / (2 * n),
accum = state.accum + state.term},
state => state.accum)
See how it doesn't use an if
, Power
, or Factorial
? The alternating signs are created simply by multiplying the last term by -1
. Computing the ever-larger exponents and factorials on each term is not only expensive and results in loss of precision, it is also unnecessary.
To get x^2
, x^4
, x^6
,... all you have to do is multiply each successive term by x^2
. To get 1/1!
, 1/3!
, 1/5!
,... all you have to do is divide each successive term by the next two numbers in the series. Start with 1
; to get 1/3!
, divide by 2 and then 3; to get 1/5!
divide by 4 and then 5, and so on.
Note that I used the m
prefix to denote decimal
values because I'm assuming that you're trying to do your calculations in decimal
for some reason (otherwise you would use Math.Cos
).
Upvotes: 1
Reputation: 11840
Something like this, perhaps:
var sineResult = listDouble.Select((item, index) =>
new {i = (index%2)*2 - 1, o = item})
.Aggregate(seno, (result, b) =>
result - b.i * ((decimal)Math.Pow(nGrau, (double)b.o) / Factorial(b.o)));
The code
i = (index%2)*2 - 1
gives you alternating 1 and -1.
The Aggregate statement sums the values, mulitplying each value by either -1 or 1.
Upvotes: 1
Reputation: 125620
You could use Aggregate
:
decimal seno = PrimeNumbers(3, 15)
.Aggregate(
new { sub = false, sum = (decimal)(nGrau * nSeno) },
(x, p) => new {
sub = !x.sub,
sum = x.sum + (x.sub ? 1 : -1) * (decimal)Math.Pow(nGrau, (double)p) / Factorial(p)
},
x => x.sum);
I didn't test that, but think it should work.
Btw. I don't think it's more readable or better then your solution. If I were you I would go with foreach
loop, but improve it a little bit:
foreach (var a in primes)
{
seno += (SumSub ? 1 : -1) * (decimal)Math.Pow(nGrau, (double)a) / Factorial(a);
SumSub = !SumSub;
}
Upvotes: 1