#1470·chartist

[Bug]:

Author: codeCraft-RitikCreated Sep 10, 2026Updated Sep 10, 2026
Labelsbug

Would you like to work on a fix?

  • Check this if you would like to implement a PR, we are more than happy to help you go through the process.

Current and expected behavior

Description

When calling roundWithPrecision(value, 0) to round a floating-point number to $0$ decimal places (i.e. to the nearest whole integer), the function ignores the digits = 0 argument and unexpectedly rounds to $8$ decimal places (the default globalPrecision).

Location in Codebase

Root Cause Analysis

In src/core/math.ts:

typescript
export function roundWithPrecision(value: number, digits?: number) {
  const precision = Math.pow(10, digits || globalPrecision);
  return Math.round(value * precision) / precision;
}

The function uses the logical OR operator (digits || globalPrecision) to handle optional parameters. In JavaScript, the number 0 is falsy:

$$0 \parallel \text{globalPrecision} \implies 8$$

When digits = 0 is passed:

  1. digits || globalPrecision evaluates to 8 (globalPrecision).
  2. precision is calculated as $10^8 = 100,000,000$ instead of $10^0 = 1$.
  3. The number is rounded to 8 decimal places instead of being rounded to an integer.

Expected vs Actual Behavior

  • Input: roundWithPrecision(3.14159, 0)
  • Expected Output: 3
  • Actual Output: 3.14159

Suggested Fix

Use the nullish coalescing operator (??) to only fall back to globalPrecision when digits is null or undefined:

typescript
export function roundWithPrecision(value: number, digits?: number) {
  const precision = Math.pow(10, digits ?? globalPrecision);
  return Math.round(value * precision) / precision;
}

Reproduction

typescript

### Chartist version

1.5.0 (latest / main)

### Possible solution

// ============================================================================
// 1. SOURCE CODE FIX: src/core/math.ts
// ============================================================================

// ❌ BEFORE (BUG):
// export function roundWithPrecision(value: number, digits?: number) {
//   const precision = Math.pow(10, digits || globalPrecision);
//   return Math.round(value * precision) / precision;
// }

// ✅ AFTER (FIX):
export function roundWithPrecision(value: number, digits?: number) {
  const precision = Math.pow(10, digits ?? globalPrecision);
  return Math.round(value * precision) / precision;
}



// ============================================================================
// 2. UNIT TESTS: src/core/math.spec.ts (or added to src/core/bound.spec.ts)
// ============================================================================

import { roundWithPrecision } from './math';

describe('Core', () => {
  describe('Math', () => {
    describe('roundWithPrecision', () => {
      it('should round to 0 decimal places when digits is 0', () => {
        expect(roundWithPrecision(3.14159, 0)).toBe(3);
        expect(roundWithPrecision(3.5, 0)).toBe(4);
        expect(roundWithPrecision(-2.7, 0)).toBe(-3);
      });

      it('should round to specified decimal places', () => {
        expect(roundWithPrecision(3.14159, 2)).toBe(3.14);
        expect(roundWithPrecision(3.14159, 4)).toBe(3.1416);
      });

      it('should fallback to globalPrecision (8 digits) when digits is omitted', () => {
        expect(roundWithPrecision(1.2345678901)).toBe(1.23456789);
      });
    });
  });
});