[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
src/core/math.ts(lines 36–39)
Root Cause Analysis
In src/core/math.ts:
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:
digits || globalPrecisionevaluates to8(globalPrecision).precisionis calculated as $10^8 = 100,000,000$ instead of $10^0 = 1$.- 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:
export function roundWithPrecision(value: number, digits?: number) {
const precision = Math.pow(10, digits ?? globalPrecision);
return Math.round(value * precision) / precision;
}Reproduction
### 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);
});
});
});
});Source: chartist-js/chartist