Since "Old School" approaches were mentioned, this is just for fun :)
This is not as old as Ptolemy, who got only about 6 digits of precision. Like him, we start with finding the sine of one degree. Then we will rotate a unit vector a degree at a time. Round-off error accumulates so we'll start at 0 degrees and rotate 22 times; then restart at 45 degrees and rotate 22 times. The rest of the table may be filled out by symmetry, by reversing and joining the table. The program uses only old-school arithmetic operations, plus, minus, times, divide. Note that some functions used, such as Dot
and FromContinuedFraction
, represent elementary arithmetic operations. It would not be too hard to carry this out on paper with a four-function calculator. [Oops, I just realized that I glossed over computing Degree
, i.e. Pi
-- oh well....Forgive me.]
We'll start by using a modern technique, Taylor series. The degree-7 Taylor polynomial gives a machine-precision approximation of Sin[1 Degree]
. The way you compute it makes a difference. The second method avoids a 1 ulp error. We calculate Cos[1 Degree]
similarly. (One could use Sqrt[1 - sin^2]
, if you wish, or your calculator has a square-root button.)
With[{x = (1. Degree)},
sin = x - x^3/3! + x^5/5! - x^7/7!
] - Sin[1. Degree]
(* 3.46945*10^-18 *)
Module[{sin},
sin = (1. Degree)^2;
sin = Fold[
sin (1 - #)/#2 &,
sin/(7 * 6),
{5 * 4, 3 * 2}
];
sin = (1. Degree) (1 - sin)
] - Sin[1. Degree]
(* 0. *)
We can put an accurate table together by rotating
trigtable = Module[{cos, sin, x, rt2},
rt2 = FromContinuedFraction[{1., 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}]; (* Sqrt[2.] *)
x = (1. Degree)^2;
sin = Fold[ (* Taylor approximation of Sin[1 Degree] *)
x (1 - #)/#2 &,
x/(7 * 6),
{5 * 4, 3 * 2}
];
sin = (1. Degree) (1 - sin);
cos = 1 - Fold[ (* Taylor approximation of Cos[1 Degree] *)
x (1 - #)/#2 &,
x/(6 * 5),
{4 * 3, 2 * 1}
];
Join[ (* Join 0-22 and reflected 45-67 tables *)
NestList[ (* 0-22 table *)
{{cos, -sin}, {sin, cos}}.# &,
{1, 0}, (* start: Cos/Sin @ 0 Degree *)
22],
Reverse@Transpose@Reverse@Transpose@NestList[ (* reflect 45-67 table *)
{{cos, -sin}, {sin, cos}}.# &,
{1, 1}/rt2 (* start: Cos/Sin @ 45 Degree *)
22]
]
];
trigtable = Join[ (* reflect 0-45 to create 0-90 table *)
Most@trigtable,
Reverse@Transpose@Reverse@Transpose@trigtable
];
The is accurate to at least the 15 decimal place in all entries.
-Max[trigtable - Table[{Cos[n Degree], Sin[n Degree]}, {n, 0, 90}] // RealExponent]
(* 15.1095 *)
Extract the cosine entries for 49 degrees (index 50) through 59 degrees:
trigtable[[50 ;; 60, 1]]
(*
{0.6560590289905073`, 0.6427876096865393`, 0.6293203910498374`,
0.6156614753256582`, 0.6018150231520482`, 0.5877852522924729`,
0.5735764363510459`, 0.5591929034707467`, 0.544639035015027`,
0.5299192642332049`, 0.5150380749100542`}
*)