Skip to content

demo(11-float-money-equality): 11 — Floating-point equality on a money amount#160

Open
EricCogen wants to merge 1 commit intomainfrom
demo/11-float-money-equality
Open

demo(11-float-money-equality): 11 — Floating-point equality on a money amount#160
EricCogen wants to merge 1 commit intomainfrom
demo/11-float-money-equality

Conversation

@EricCogen
Copy link
Copy Markdown
Owner

11 — Floating-point equality on a money amount

Expected verdict: ❌ Fails — GauntletCI should fire GCI0049 (float/double equality comparison).

What changed

A new LegacyDiscountCalculator works in double (because it was
ported from a JavaScript pricing prototype) and tests for an exact
zero-net result with ==:

public sealed class LegacyDiscountCalculator
{
    public double NetTotal(double subtotal, double discount)
    {
        var net = subtotal - discount;
        if (net == 0.0)
        {
            return 0.0;
        }
        return net;
    }
}

For most inputs subtotal - discount is exactly representable, but for
values like 0.1 + 0.2 - 0.3 the result is 5.55e-17, not 0.0, and
the comparison silently returns false.

Why this is risky

  • Money values must never be compared with == in double/float.
    Binary floating-point cannot exactly represent most decimal fractions,
    so a "zero net" check returns the wrong answer for a single rounding
    ulp difference.
  • The bug is path-dependent: it fires only for some discount/subtotal
    pairs, so it sails through unit tests that use round numbers and
    surfaces in production for the one customer with $19.99 and a
    $19.99 discount.
  • The fix is either an epsilon comparison (Math.Abs(net) < 1e-9) or
    — much better for money — using decimal end-to-end.

What GauntletCI catches

GCI0049 Float/Double Equality Comparison== (or !=) on the
same line as a floating-point literal in a non-test file.

…y amount

See scenarios/11-float-money-equality/README.md for the expected verdict.
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GauntletCI found issues in this PR. See inline comments for details.

public double NetTotal(double subtotal, double discount)
{
var net = subtotal - discount;
if (net == 0.0)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCI0049 — Float/Double Equality Comparison

Direct equality comparison on a floating-point value — use an epsilon threshold instead

Evidence:

Line 8: if (net == 0.0)

⚠️ Why it matters: Floating-point arithmetic is inexact due to binary representation. Two values that are mathematically equal may differ by a tiny rounding error, causing == to return false and != to return true unexpectedly.

💡 Suggested action: Compare with an epsilon: Math.Abs(a - b) < 1e-9. For financial calculations use decimal instead of float/double.

Confidence: Medium | Severity: Info

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7265b3e33b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

public double NetTotal(double subtotal, double discount)
{
var net = subtotal - discount;
if (net == 0.0)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid exact equality on floating-point totals

Replace this == check with a tolerance-based comparison (or switch to decimal) because subtotal - discount in double can produce tiny residuals for mathematically equal amounts (for example, values derived from 0.1 + 0.2 versus 0.3). In those cases this branch is skipped and a near-zero nonzero result leaks out, which is incorrect for zero-net pricing logic.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant