Skip to content

IsNormal(Zero) returns true, unlike int/decimal/BigInteger, so generic math treats PreciseNumber zero as a normal number #122

Description

@matt-edmondson

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions