@@ -236,7 +236,7 @@ public static PreciseNumber Tan(PreciseNumber x, int significantDigits)
236236 RequireSignificantDigits ( significantDigits ) ;
237237 int working = significantDigits + TrigonometricGuardDigits ;
238238 ( PreciseNumber sin , PreciseNumber cos ) = SinCos ( x , working ) ;
239- return Divide ( sin , cos , significantDigits ) ;
239+ return DivideApproximation ( sin , cos , working , significantDigits ) ;
240240 }
241241
242242 /// <summary>
@@ -281,7 +281,7 @@ public static PreciseNumber Asin(PreciseNumber x, int significantDigits)
281281
282282 if ( magnitude == One )
283283 {
284- PreciseNumber halfPi = Divide ( PiTo ( working ) , Two , significantDigits ) ;
284+ PreciseNumber halfPi = DivideApproximation ( PiTo ( working ) , Two , working , significantDigits ) ;
285285 return x . Significand . Sign > 0 ? halfPi : - halfPi ;
286286 }
287287
@@ -431,7 +431,7 @@ public static PreciseNumber Atan2(PreciseNumber y, PreciseNumber x, int signific
431431 return Zero ;
432432 }
433433
434- PreciseNumber halfPi = Divide ( PiTo ( working ) , Two , significantDigits ) ;
434+ PreciseNumber halfPi = DivideApproximation ( PiTo ( working ) , Two , working , significantDigits ) ;
435435 return y . Significand . Sign > 0 ? halfPi : - halfPi ;
436436 }
437437
@@ -562,7 +562,7 @@ public static PreciseNumber TanPi(PreciseNumber x, int significantDigits)
562562 RequireSignificantDigits ( significantDigits ) ;
563563 int working = significantDigits + TrigonometricGuardDigits ;
564564 ( PreciseNumber sin , PreciseNumber cos ) = SinCosPi ( x , working ) ;
565- return Divide ( sin , cos , significantDigits ) ;
565+ return DivideApproximation ( sin , cos , working , significantDigits ) ;
566566 }
567567
568568 /// <summary>
@@ -599,7 +599,7 @@ public static PreciseNumber AsinPi(PreciseNumber x, int significantDigits)
599599 }
600600
601601 int working = significantDigits + TrigonometricGuardDigits ;
602- return Divide ( Asin ( x , working ) , PiTo ( working ) , significantDigits ) ;
602+ return DivideApproximation ( Asin ( x , working ) , PiTo ( working ) , working , significantDigits ) ;
603603 }
604604
605605 /// <summary>
@@ -636,7 +636,7 @@ public static PreciseNumber AcosPi(PreciseNumber x, int significantDigits)
636636 }
637637
638638 int working = significantDigits + TrigonometricGuardDigits ;
639- return Divide ( Acos ( x , working ) , PiTo ( working ) , significantDigits ) ;
639+ return DivideApproximation ( Acos ( x , working ) , PiTo ( working ) , working , significantDigits ) ;
640640 }
641641
642642 /// <summary>
@@ -664,7 +664,7 @@ public static PreciseNumber AtanPi(PreciseNumber x, int significantDigits)
664664 }
665665
666666 int working = significantDigits + TrigonometricGuardDigits ;
667- return Divide ( Atan ( x , working ) , PiTo ( working ) , significantDigits ) ;
667+ return DivideApproximation ( Atan ( x , working ) , PiTo ( working ) , working , significantDigits ) ;
668668 }
669669
670670 /// <summary>
@@ -692,7 +692,7 @@ public static PreciseNumber DegreesToRadians(PreciseNumber degrees, int signific
692692 {
693693 RequireSignificantDigits ( significantDigits ) ;
694694 int working = significantDigits + TrigonometricGuardDigits ;
695- return Divide ( Multiply ( degrees , PiTo ( working ) ) , OneEighty , significantDigits ) ;
695+ return DivideApproximation ( Multiply ( degrees , PiTo ( working ) ) , OneEighty , working , significantDigits ) ;
696696 }
697697
698698 /// <summary>
@@ -720,7 +720,7 @@ public static PreciseNumber RadiansToDegrees(PreciseNumber radians, int signific
720720 {
721721 RequireSignificantDigits ( significantDigits ) ;
722722 int working = significantDigits + TrigonometricGuardDigits ;
723- return Divide ( Multiply ( radians , OneEighty ) , PiTo ( working ) , significantDigits ) ;
723+ return DivideApproximation ( Multiply ( radians , OneEighty ) , PiTo ( working ) , working , significantDigits ) ;
724724 }
725725
726726 /// <summary>
@@ -853,6 +853,23 @@ private static (PreciseNumber Sin, PreciseNumber Cos) SinCosSeries(PreciseNumber
853853 $ "The trigonometric series did not converge to { workingDigits . ToString ( InvariantCulture ) } significant digits.") ;
854854 }
855855
856+ /// <summary>
857+ /// Divides a value that is already an approximation, then rounds to the digits the caller asked for.
858+ /// </summary>
859+ /// <param name="numerator">The dividend, carried at <paramref name="workingDigits"/>.</param>
860+ /// <param name="denominator">The divisor.</param>
861+ /// <param name="workingDigits">The significant digits the operands were computed to.</param>
862+ /// <param name="significantDigits">The number of significant digits to produce.</param>
863+ /// <returns>The quotient, rounded to <paramref name="significantDigits"/>.</returns>
864+ /// <remarks>
865+ /// <see cref="Divide(PreciseNumber, PreciseNumber, int)"/> returns a terminating quotient exactly,
866+ /// without rounding it. When an operand is a rounded approximation, such as π at working precision,
867+ /// that exact quotient still carries the operand's guard digits, and they are wrong. Rounding
868+ /// afterwards keeps the result to the digits requested whether or not the quotient terminates.
869+ /// </remarks>
870+ private static PreciseNumber DivideApproximation ( PreciseNumber numerator , PreciseNumber denominator , int workingDigits , int significantDigits ) =>
871+ Divide ( numerator , denominator , workingDigits ) . ReduceSignificance ( significantDigits ) ;
872+
856873 /// <summary>
857874 /// Sums the arc tangent series for a small argument.
858875 /// </summary>
0 commit comments