9

For several days, I've been wondering how it would be possible of computing the sine of huge numbers with magnitude around 100000! (radians). The factorial is just an example the number itself can be any not just a factorial product ...) I obviously don't use double but cpp_rational from the boost multiprecision library. But I can't simply do 100000! mod 2pi and then use the builtin function sinl (I don't need more than 10 decimal digits..) as I'd need several million digits of pi to do this accurately.

Is there any way to achieve this?

Spektre
  • 49,595
  • 11
  • 110
  • 380
borchero
  • 5,562
  • 8
  • 46
  • 72
  • 2
    This is a very difficult problem indeed: Good math libs do in fact use large numbers of pi's digits (the infinite-pi approximation) while others use a worse, but cheaper, finite-pi approximation. – Iwillnotexist Idonotexist Jul 04 '16 at 21:32
  • @duffymo you missed the point. By some astronomical units, so to say. – sehe Jul 04 '16 at 22:31
  • Can't win 'em all. Maybe we should ask why/how he intended to calculate 100000!. That's just ignorant. – duffymo Jul 04 '16 at 22:59
  • without knowing more about the `x` from the `sin(x)` you can only use precise enough **Pi** constant. If you got some more knowledge about the result and or argument then you can exploit it. For example on geometrical problems you can usually apply **CORDIC**. On algebraic you can use identities or similarities. If it is just some sub-result sometimes porting to complex domain helps (in `exp` form with euler's formula)... to help we would need to know more... – Spektre Jul 14 '16 at 12:21

4 Answers4

5

This is in general a non trivial task, as it has many similarities with the Discrete Logarithm Problem, which implies in its turn a computationally intensive calculation.
That said, your calculation could be easier if you consider the logarithm of 100000!/pi, as it reduces to the sum of logs of all positive integers equal or less than 100000, and a subtraction: log(N!/pi) = \sum_{i=0}^N (log i) - log(pi). If you exponentiate this number, you have an approximate evaluation of (N!/pi). Subtract the integer part, and multiply the result by pi. This is the estimate of your N! mod pi.
In formula:

As you may notice, I used many times the word approximate. This is due to the following considerations:

  • you have to calculate many logs, which have some cost and errors
  • you may want to change the base of your log, according to your problem size; this again is going to affect the accuracy and the precision of your result
  • you have to exponentiate back: small errors may lead to large ones
  • subtract large numbers: may lead to large cancellations
  • multiply by pi and evaluate the sin: again errors

If you think it may be beneficial, consider using the Stirling's approximation.

As a final remark, there is not an easy solution to these kind of problems, you always has to deal with them case by case.

Iwillnotexist Idonotexist
  • 13,297
  • 4
  • 43
  • 66
fedino
  • 913
  • 1
  • 9
  • 15
  • The problem is: I don't actually compute `sin(100000!)` but just have a number _as big as_ `100000!` for which I want to compute the sine. – borchero Jul 05 '16 at 08:36
  • Ok, you can use `log`s for any positive number, right? :-) – fedino Jul 05 '16 at 08:38
  • Yeah of course, but I can't actually use the sum the way you're describing it. – borchero Jul 05 '16 at 08:39
  • This is true. In that case, you do not need the sum. I assume that you can represent somehow your large input number, therefore you can calculate its log. And of course you can subtract. The real point here is, how to properly dimension your log base. – fedino Jul 05 '16 at 08:41
  • Base 2 mostly is quite a good choice in computer programming .. because you can use bitshifts to exponentiate, which is rather fast. – borchero Jul 05 '16 at 08:43
  • Yes in general, but consider you will obtain larger numbers in log if your base is small, and then you exponentiate 2 with that number. You may pay being fast with being unaccurate. Maybe you could use a larger representation of `pi` and take a larger base. – fedino Jul 05 '16 at 08:46
  • @IwillnotexistIdonotexist: you did well, it is much more readable, and this shows the working principle (which does not depends on the factorial). It also shows that I missed a factor `2` in front of `pi`! I did not manage to correct it; if you do, it would be of great help. ;-) – fedino Jul 06 '16 at 09:46
  • @OliverBorchert adding to the exponent is much faster than shifting bits, still :) – sehe Jul 06 '16 at 14:14
1

Note: = pi

To calculate sin of a very big number in radians (Change them to multiples of  by dividing by 3.1415)
1. Observe this: sin 0 = 0, sin 0.5pi = 1, sin pi = 1, sin1.5pi = -1, sin 2pi=0
2. Even or odd integer values in front of pi, the sin is 0
3. For real values (those with decimal points), for even numbers before the decimal point, take it as the 0. something as the value of the sine, for odd, then take the 1. something as the value of the sine.
4. See examples *Note that sin and cosine are periodic in nature, that is why it is possible to do it in this way for big or small numbers. :)

Eg. (Use your calculators to check out the calculations)

1.0 In radians: sin 100 = -0.506
Divide by 3.1415
Do in deg
Sin 31.831pi (31.831 is a real value) = sin1.831(180) =-0.506, check

2.0 In radians: sin 50 = -0.2623
Divide by 3.1415
Do in deg
Sin 15.9155pi = sin1.9155 (180) =-0.2623

3.0 In radians: sin 700 = 0.5439
Divide by 3.1415
Do in deg
Sin 222.8169pi = sin0.8169 (180) =-0.5440, check

4.0 In radians: sin 15000 = 0.8934
Divide by 3.1415
Do in deg
Sin 4774.6483pi = sin0.6483 (180) = 0.893, check

You can see that all the answers checked out with the direct calculation of the values using the calculator in radian mode. Hope this is helpful.

If you want to write out a compute program, best of luck in figuring out the algorithm.

-1

Wikipedia lists many trigonometric identities. Some include products in the argument, such as Chebyshev's Method which is recursive but the recursion could be reduced using Chebyshev Polynomials and/or memoization. If your argument is as easy to factor as a factorial, then this might be a feasible method.

John
  • 7,301
  • 2
  • 16
  • 23
-4

Maybe you can use cpp_rational to compute the sinus directly from your very large number:

sin(x): x/1! - x^3/3! + x^5/5! - x^7/7! + ...

Repeat this series until no (for your application) significant changes occur. This way you avoid the number pi completely.

CAF
  • 1,090
  • 9
  • 6
  • The taylor series expansion at x=0 is only an approximation for the first few periods of the sine, or I'd have to loop through the sum several thousand times which is not practical (can't use the expansion at x=very big either because I'd need to compute the sine...) – borchero Jul 05 '16 at 08:47
  • 1
    As you see, the `sin` Taylor expantion is alternating in its sign. So you end up summing many many terms, with some cancellation. This may decrease the accuracy, such that you have a stable result, but that is wrong. Also consider that you need to evaluate the power of an already very large number, which is going worser and worser. – fedino Jul 05 '16 at 08:49
  • @fedino With arbitrary precision rationals, that won't happen. – Baum mit Augen Jul 05 '16 at 16:57
  • @OliverBorchert How long does it take to calculate one result in that order of magnitude with the series representation? – Baum mit Augen Jul 05 '16 at 16:58
  • 1
    @BaummitAugen you won't be able to finish .. 100000! ^ 100 is already extremely time consuming and you'd need polynoms with an exponent of 100000! / 3 approximately which is certainly not possible – borchero Jul 05 '16 at 17:01