Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions PreciseNumber.Test/PreciseNumberExponentialTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,42 @@ public void TestLog2P1AndLog10P1KeepTheDigitsOfASmallArgument()
"Log10P1(1E-30) is wrong");
}

[TestMethod]
public void TestLogInABaseRoundsATerminatingQuotientToTheDigitsAskedFor()
{
// ln 1e5 / ln 1e4 is exactly 1.25 once both logarithms are carried to the same working width,
// so an unrounded Divide hands back three digits for a one-digit request.
PreciseNumber oneDigit = PreciseNumber.Log(Parse("1E5"), Parse("1E4"), 1);
Assert.AreEqual(PreciseNumber.One, oneDigit, "Log(1E5, 1E4, 1) is wrong");
Assert.AreEqual(1, oneDigit.SignificantDigits, "Log(1E5, 1E4, 1) returned more digits than asked for");

PreciseNumber twoDigits = PreciseNumber.Log(Parse("1E5"), Parse("1E4"), 2);
Assert.AreEqual(2, twoDigits.SignificantDigits, "Log(1E5, 1E4, 2) returned more digits than asked for");
Assert.AreEqual(Parse("1.3"), twoDigits, "Log(1E5, 1E4, 2) is wrong");

Assert.AreEqual(Parse("1.25"), PreciseNumber.Log(Parse("1E5"), Parse("1E4"), 3), "Log(1E5, 1E4, 3) is wrong");
Assert.AreEqual(Parse("1.8"), PreciseNumber.Log(Parse("1E7"), Parse("1E4"), 2), "Log(1E7, 1E4, 2) is wrong");
}

[TestMethod]
public void TestDividedLogarithmsNeverReturnMoreDigitsThanAskedFor()
{
// Log2, Log2P1 and Log10P1 finish with the same division as a logarithm in a chosen base, so
// they share its rule: the result is rounded to the request whether or not the quotient
// terminates.
for (int digits = 1; digits <= 4; digits++)
{
for (int i = 1; i <= 64; i++)
{
PreciseNumber x = Parse(i.ToString(CultureInfo.InvariantCulture));
Assert.IsLessThanOrEqualTo(digits, PreciseNumber.Log2(x, digits).SignificantDigits, $"Log2({i}, {digits}) returned more digits than asked for");
Assert.IsLessThanOrEqualTo(digits, PreciseNumber.Log2P1(x, digits).SignificantDigits, $"Log2P1({i}, {digits}) returned more digits than asked for");
Assert.IsLessThanOrEqualTo(digits, PreciseNumber.Log10P1(x, digits).SignificantDigits, $"Log10P1({i}, {digits}) returned more digits than asked for");
Assert.IsLessThanOrEqualTo(digits, PreciseNumber.Log(x, Parse("1E4"), digits).SignificantDigits, $"Log({i}, 1E4, {digits}) returned more digits than asked for");
}
}
}

[TestMethod]
public void TestPrecisionFollowsTheWiderOperandRatherThanDouble()
{
Expand Down
8 changes: 4 additions & 4 deletions PreciseNumber/PreciseNumber.Exponentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public static PreciseNumber Log(PreciseNumber x, PreciseNumber newBase, int sign
{
RequireSignificantDigits(significantDigits);
int working = significantDigits + ExponentialGuardDigits;
return Divide(Log(x, working), Log(newBase, working), significantDigits);
return DivideApproximation(Log(x, working), Log(newBase, working), working, significantDigits);
}

/// <summary>
Expand Down Expand Up @@ -224,7 +224,7 @@ public static PreciseNumber Log2(PreciseNumber x, int significantDigits)
{
RequireSignificantDigits(significantDigits);
int working = significantDigits + ExponentialGuardDigits;
return Divide(Log(x, working), Ln2To(working), significantDigits);
return DivideApproximation(Log(x, working), Ln2To(working), working, significantDigits);
}

/// <summary>
Expand Down Expand Up @@ -354,7 +354,7 @@ public static PreciseNumber Log2P1(PreciseNumber x, int significantDigits)
}

int working = significantDigits + ExponentialGuardDigits;
return Divide(LogP1(x, working), Ln2To(working), significantDigits);
return DivideApproximation(LogP1(x, working), Ln2To(working), working, significantDigits);
}

/// <summary>
Expand Down Expand Up @@ -386,7 +386,7 @@ public static PreciseNumber Log10P1(PreciseNumber x, int significantDigits)
}

int working = significantDigits + ExponentialGuardDigits;
return Divide(LogP1(x, working), Ln10To(working), significantDigits);
return DivideApproximation(LogP1(x, working), Ln10To(working), working, significantDigits);
}

/// <summary>
Expand Down
Loading