What's wrong
PreciseNumber/PreciseNumber.cs:1094:
public static bool IsNormal(PreciseNumber value) => true;
INumberBase<T>.IsNormal is false for zero on every built-in numeric type:
int.IsNormal(0) // false
decimal.IsNormal(0m) // false
BigInteger.IsNormal(BigInteger.Zero) // false
PreciseNumber.IsNormal(PreciseNumber.Zero) // true <-- inconsistent
Why it matters
Generic math code written against INumberBase<T> often uses IsNormal as a "non-zero, finite, not subnormal" guard, for example before dividing or taking a log. With PreciseNumber, zero passes that guard, so the same generic algorithm behaves differently than it does with decimal or BigInteger.
Suggested fix
public static bool IsNormal(PreciseNumber value) => !value.Significand.IsZero;
Note that IsSubnormal (line 1114) is currently written as !IsNormal(value). Once IsNormal is fixed, that definition would make IsSubnormal(Zero) true, which is also wrong. Change it to => false, which is what BigInteger and decimal do.
Acceptance: IsNormal(Zero) == false, IsNormal(x) == true for any non-zero x, and IsSubnormal(x) == false for every x, with tests added.
What's wrong
PreciseNumber/PreciseNumber.cs:1094:INumberBase<T>.IsNormalis false for zero on every built-in numeric type:Why it matters
Generic math code written against
INumberBase<T>often usesIsNormalas a "non-zero, finite, not subnormal" guard, for example before dividing or taking a log. WithPreciseNumber, zero passes that guard, so the same generic algorithm behaves differently than it does withdecimalorBigInteger.Suggested fix
Note that
IsSubnormal(line 1114) is currently written as!IsNormal(value). OnceIsNormalis fixed, that definition would makeIsSubnormal(Zero)true, which is also wrong. Change it to=> false, which is whatBigIntegeranddecimaldo.Acceptance:
IsNormal(Zero) == false,IsNormal(x) == truefor any non-zerox, andIsSubnormal(x) == falsefor everyx, with tests added.