From 39c715d916d69e83795932260f1681df3241db91 Mon Sep 17 00:00:00 2001 From: Matt Mayer <152770+matthewmayer@users.noreply.github.com> Date: Thu, 28 Dec 2023 01:46:55 +0700 Subject: [PATCH] fix(number): improve float generation for precisions of form 10^-n (#2581) --- src/modules/number/index.ts | 7 +++- .../__snapshots__/finance.spec.ts.snap | 16 ++++---- .../__snapshots__/location.spec.ts.snap | 4 +- test/modules/number.spec.ts | 38 ++++++++++++++----- 4 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/modules/number/index.ts b/src/modules/number/index.ts index 91d987771e0..4becb3480d4 100644 --- a/src/modules/number/index.ts +++ b/src/modules/number/index.ts @@ -150,7 +150,12 @@ export class NumberModule extends SimpleModuleBase { throw new FakerError(`Precision should be greater than 0.`); } - const factor = 1 / precision; + const logPrecision = Math.log10(precision); + // Workaround to get integer values for the inverse of all precisions of the form 10^-n + const factor = + precision < 1 && Number.isInteger(logPrecision) + ? 10 ** -logPrecision + : 1 / precision; const int = this.int({ min: min * factor, max: max * factor, diff --git a/test/modules/__snapshots__/finance.spec.ts.snap b/test/modules/__snapshots__/finance.spec.ts.snap index 324aad22bf9..b2478f58ea4 100644 --- a/test/modules/__snapshots__/finance.spec.ts.snap +++ b/test/modules/__snapshots__/finance.spec.ts.snap @@ -24,13 +24,13 @@ exports[`finance > 42 > amount > with min and max option 1`] = `"24.98"`; exports[`finance > 42 > amount > with min option 1`] = `"380.79"`; -exports[`finance > 42 > amount > with min, leagcy max, leagcy dec and leagcy symbol 1`] = `"$24.98161"`; +exports[`finance > 42 > amount > with min, leagcy max, leagcy dec and leagcy symbol 1`] = `"$24.98160"`; -exports[`finance > 42 > amount > with min, max and dec option 1`] = `"24.98161"`; +exports[`finance > 42 > amount > with min, max and dec option 1`] = `"24.98160"`; -exports[`finance > 42 > amount > with min, max, dec and symbol option 1`] = `"#24.98161"`; +exports[`finance > 42 > amount > with min, max, dec and symbol option 1`] = `"#24.98160"`; -exports[`finance > 42 > amount > with min, max, dec, symbol and autoFormat option 1`] = `"#24.98161"`; +exports[`finance > 42 > amount > with min, max, dec, symbol and autoFormat option 1`] = `"#24.98160"`; exports[`finance > 42 > bic > noArgs 1`] = `"UYETSCLLG53"`; @@ -244,13 +244,13 @@ exports[`finance > 1337 > amount > with min and max option 1`] = `"20.48"`; exports[`finance > 1337 > amount > with min option 1`] = `"269.40"`; -exports[`finance > 1337 > amount > with min, leagcy max, leagcy dec and leagcy symbol 1`] = `"$20.48099"`; +exports[`finance > 1337 > amount > with min, leagcy max, leagcy dec and leagcy symbol 1`] = `"$20.48098"`; -exports[`finance > 1337 > amount > with min, max and dec option 1`] = `"20.48099"`; +exports[`finance > 1337 > amount > with min, max and dec option 1`] = `"20.48098"`; -exports[`finance > 1337 > amount > with min, max, dec and symbol option 1`] = `"#20.48099"`; +exports[`finance > 1337 > amount > with min, max, dec and symbol option 1`] = `"#20.48098"`; -exports[`finance > 1337 > amount > with min, max, dec, symbol and autoFormat option 1`] = `"#20.48099"`; +exports[`finance > 1337 > amount > with min, max, dec, symbol and autoFormat option 1`] = `"#20.48098"`; exports[`finance > 1337 > bic > noArgs 1`] = `"OEFHLYG18IL"`; diff --git a/test/modules/__snapshots__/location.spec.ts.snap b/test/modules/__snapshots__/location.spec.ts.snap index cfdc45f4b98..b4e2586b184 100644 --- a/test/modules/__snapshots__/location.spec.ts.snap +++ b/test/modules/__snapshots__/location.spec.ts.snap @@ -74,7 +74,7 @@ exports[`location > 42 > longitude > with precision option 1`] = `-45.1655588485 exports[`location > 42 > nearbyGPSCoordinate > near origin 1`] = ` [ - 0.08140632875358443, + 0.08140632875358447, -0.08093642792425726, ] `; @@ -234,7 +234,7 @@ exports[`location > 1211 > longitude > with precision option 1`] = `154.26725534 exports[`location > 1211 > nearbyGPSCoordinate > near origin 1`] = ` [ - -0.02872111236834616, + -0.02872111236834621, 0.05959024752564801, ] `; diff --git a/test/modules/number.spec.ts b/test/modules/number.spec.ts index 97061d56ffe..81a1e992c72 100644 --- a/test/modules/number.spec.ts +++ b/test/modules/number.spec.ts @@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'; import { faker, FakerError, SimpleFaker } from '../../src'; import { MERSENNE_MAX_VALUE } from '../internal/mersenne-test-utils'; import { seededTests } from '../support/seeded-runs'; +import { times } from './../support/times'; describe('number', () => { seededTests(faker, 'number', (t) => { @@ -259,17 +260,36 @@ describe('number', () => { expect(results).toEqual([0, 0.4, 0.8, 1.2, 1.6]); }); - it('provides numbers with an exact precision', () => { - for (let i = 0; i < 100; i++) { - const actual = faker.number.float({ - min: 0.5, - max: 0.99, - precision: 0.01, - }); - expect(actual).toBe(Number(actual.toFixed(2))); - } + it('provides numbers with a given precision of 0.2', () => { + const results = [ + ...new Set( + Array.from({ length: 50 }, () => + faker.number.float({ + min: 0, + max: 0.4, + precision: 0.2, + }) + ) + ), + ].sort(); + + expect(results).toEqual([0, 0.2, 0.4]); }); + it.each(times(18))( + `provides numbers with an exact precision of 10^-%d`, + (exponent) => { + for (let i = 0; i < 100; i++) { + const actual = faker.number.float({ + min: 0.5, + max: 0.99, + precision: 10 ** -exponent, + }); + expect(actual).toBe(Number(actual.toFixed(exponent))); + } + } + ); + it('throws an error for precision 0', () => { expect(() => faker.number.float({ precision: 0 })).toThrow( new FakerError('Precision should be greater than 0.')