diff --git a/src/modules/color/index.ts b/src/modules/color/index.ts index 57b906a376d..a9b39377668 100644 --- a/src/modules/color/index.ts +++ b/src/modules/color/index.ts @@ -389,7 +389,7 @@ export class ColorModule extends ModuleBase { color = Array.from({ length: 3 }, () => this.faker.number.int(255)); if (includeAlpha) { - color.push(this.faker.number.float({ precision: 0.01 })); + color.push(this.faker.number.float({ multipleOf: 0.01 })); cssFunction = 'rgba'; } @@ -470,7 +470,7 @@ export class ColorModule extends ModuleBase { }): string | number[]; cmyk(options?: { format?: ColorFormat }): string | number[] { const color: string | number[] = Array.from({ length: 4 }, () => - this.faker.number.float({ precision: 0.01 }) + this.faker.number.float({ multipleOf: 0.01 }) ); return toColorFormat(color, options?.format || 'decimal', 'cmyk'); } @@ -580,7 +580,7 @@ export class ColorModule extends ModuleBase { }): string | number[] { const hsl: number[] = [this.faker.number.int(360)]; for (let i = 0; i < (options?.includeAlpha ? 3 : 2); i++) { - hsl.push(this.faker.number.float({ precision: 0.01 })); + hsl.push(this.faker.number.float({ multipleOf: 0.01 })); } return toColorFormat( @@ -686,7 +686,7 @@ export class ColorModule extends ModuleBase { }): string | number[] { const hsl: number[] = [this.faker.number.int(360)]; for (let i = 0; i < 2; i++) { - hsl.push(this.faker.number.float({ precision: 0.01 })); + hsl.push(this.faker.number.float({ multipleOf: 0.01 })); } return toColorFormat(hsl, options?.format || 'decimal', 'hwb'); @@ -765,10 +765,10 @@ export class ColorModule extends ModuleBase { format?: ColorFormat; }): string | number[]; lab(options?: { format?: ColorFormat }): string | number[] { - const lab = [this.faker.number.float({ precision: 0.000001 })]; + const lab = [this.faker.number.float({ multipleOf: 0.000001 })]; for (let i = 0; i < 2; i++) { lab.push( - this.faker.number.float({ min: -100, max: 100, precision: 0.0001 }) + this.faker.number.float({ min: -100, max: 100, multipleOf: 0.0001 }) ); } @@ -860,9 +860,9 @@ export class ColorModule extends ModuleBase { format?: ColorFormat; }): string | number[]; lch(options?: { format?: ColorFormat }): string | number[] { - const lch = [this.faker.number.float({ precision: 0.000001 })]; + const lch = [this.faker.number.float({ multipleOf: 0.000001 })]; for (let i = 0; i < 2; i++) { - lch.push(this.faker.number.float({ max: 230, precision: 0.1 })); + lch.push(this.faker.number.float({ max: 230, multipleOf: 0.1 })); } return toColorFormat(lch, options?.format || 'decimal', 'lch'); @@ -970,7 +970,7 @@ export class ColorModule extends ModuleBase { } const color = Array.from({ length: 3 }, () => - this.faker.number.float({ precision: 0.0001 }) + this.faker.number.float({ multipleOf: 0.0001 }) ); return toColorFormat( color, diff --git a/src/modules/datatype/index.ts b/src/modules/datatype/index.ts index b8830610548..daec9640dca 100644 --- a/src/modules/datatype/index.ts +++ b/src/modules/datatype/index.ts @@ -75,7 +75,7 @@ export class DatatypeModule extends SimpleModuleBase { const { min = 0, max = min + 99999, precision = 1 } = options; - return this.faker.number.float({ min, max, precision }); + return this.faker.number.float({ min, max, multipleOf: precision }); } /** @@ -142,7 +142,7 @@ export class DatatypeModule extends SimpleModuleBase { const { min = 0, max = min + 99999, precision = 0.01 } = options; - return this.faker.number.float({ min, max, precision }); + return this.faker.number.float({ min, max, multipleOf: precision }); } /** diff --git a/src/modules/finance/index.ts b/src/modules/finance/index.ts index 576ca0dbc92..4caa77b028c 100644 --- a/src/modules/finance/index.ts +++ b/src/modules/finance/index.ts @@ -601,7 +601,7 @@ export class FinanceModule extends ModuleBase { const randValue = this.faker.number.float({ max, min, - precision: 10 ** -dec, + multipleOf: 10 ** -dec, }); const formattedString = autoFormat diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts index edc00ea9a01..635b3e09d4f 100644 --- a/src/modules/helpers/index.ts +++ b/src/modules/helpers/index.ts @@ -979,7 +979,6 @@ export class SimpleHelpersModule extends SimpleModuleBase { const random = this.faker.number.float({ min: 0, max: total, - precision: 1e-9, }); let current = 0; for (const { weight, value } of array) { diff --git a/src/modules/location/index.ts b/src/modules/location/index.ts index 6d15741dc7e..b06af49e656 100644 --- a/src/modules/location/index.ts +++ b/src/modules/location/index.ts @@ -579,7 +579,7 @@ export class LocationModule extends ModuleBase { const { max = 90, min = legacyMin, precision = legacyPrecision } = options; - return this.faker.number.float({ min, max, precision: 10 ** -precision }); + return this.faker.number.float({ min, max, multipleOf: 10 ** -precision }); } /** @@ -732,7 +732,7 @@ export class LocationModule extends ModuleBase { const { max = 180, min = legacyMin, precision = legacyPrecision } = options; - return this.faker.number.float({ max, min, precision: 10 ** -precision }); + return this.faker.number.float({ max, min, multipleOf: 10 ** -precision }); } /** @@ -1207,7 +1207,7 @@ export class LocationModule extends ModuleBase { const angleRadians = this.faker.number.float({ max: 2 * Math.PI, - precision: 0.00001, + multipleOf: 0.00001, }); // in ° radians const radiusMetric = isMetric ? radius : radius * 1.60934; // in km @@ -1215,7 +1215,7 @@ export class LocationModule extends ModuleBase { const distanceInKm = this.faker.number.float({ max: radiusMetric, - precision: 0.001, + multipleOf: 0.001, }) * errorCorrection; // in km /** diff --git a/src/modules/number/index.ts b/src/modules/number/index.ts index 4becb3480d4..2d1af9ccbd9 100644 --- a/src/modules/number/index.ts +++ b/src/modules/number/index.ts @@ -1,4 +1,5 @@ import { FakerError } from '../../errors/faker-error'; +import { deprecated } from '../../internal/deprecated'; import { SimpleModuleBase } from '../../internal/module-base'; /** @@ -85,14 +86,18 @@ export class NumberModule extends SimpleModuleBase { } /** - * Returns a single random floating-point number for a given precision or range and precision. - * The lower bound is inclusive, the upper bound is exclusive, unless precision is passed. + * Returns a single random floating-point number. + * The lower bound is inclusive, the upper bound is exclusive, unless `multipleOf` is passed. * * @param options Upper bound or options object. * @param options.min Lower bound for generated number. Defaults to `0.0`. * @param options.max Upper bound for generated number. Defaults to `1.0`. * @param options.precision Precision of the generated number, for example `0.01` will round to 2 decimal points. * If precision is passed, the upper bound is inclusive. + * @param options.multipleOf The generated number will be a multiple of this property. + * This property can be used to limit the result to a specific number of decimal digits. + * For example `0.01` will round to 2 decimal points. + * If multipleOf is passed, the upper bound is inclusive. * * @throws When `min` is greater than `max`. * @throws When `precision` is negative. @@ -102,8 +107,8 @@ export class NumberModule extends SimpleModuleBase { * faker.number.float(3) // 2.367973240558058 * faker.number.float({ min: -1000000 }) //-780678.849672846 * faker.number.float({ max: 100 }) // 17.3687307164073 - * faker.number.float({ precision: 0.1 }) // 0.9 - * faker.number.float({ min: 10, max: 100, precision: 0.001 }) // 35.415 + * faker.number.float({ multipleOf: 0.25 }) // 3.75 + * faker.number.float({ min: 10, max: 100, multipleOf: 0.001 }) // 35.415 * * @since 8.0.0 */ @@ -125,8 +130,15 @@ export class NumberModule extends SimpleModuleBase { max?: number; /** * Precision of the generated number. + * + * @deprecated Use `multipleOf` instead. */ precision?: number; + /** + * The generated number will be a multiple of this property. + * If multipleOf is passed, the upper bound is inclusive. + */ + multipleOf?: number; } = {} ): number { if (typeof options === 'number') { @@ -135,7 +147,17 @@ export class NumberModule extends SimpleModuleBase { }; } - const { min = 0, max = 1, precision } = options; + // eslint-disable-next-line deprecation/deprecation + const { min = 0, max = 1, precision, multipleOf = precision } = options; + + if (precision !== undefined) { + deprecated({ + deprecated: 'faker.number.float({ precision })', + proposed: 'faker.number.float({ multipleOf })', + since: '8.4', + until: '9.0', + }); + } if (max === min) { return min; @@ -145,17 +167,18 @@ export class NumberModule extends SimpleModuleBase { throw new FakerError(`Max ${max} should be greater than min ${min}.`); } - if (precision !== undefined) { - if (precision <= 0) { - throw new FakerError(`Precision should be greater than 0.`); + if (multipleOf !== undefined) { + if (multipleOf <= 0) { + // TODO @xDivisionByZerox: Clean up in v9.0 + throw new FakerError(`multipleOf/precision should be greater than 0.`); } - const logPrecision = Math.log10(precision); - // Workaround to get integer values for the inverse of all precisions of the form 10^-n + const logPrecision = Math.log10(multipleOf); + // Workaround to get integer values for the inverse of all multiples of the form 10^-n const factor = - precision < 1 && Number.isInteger(logPrecision) + multipleOf < 1 && Number.isInteger(logPrecision) ? 10 ** -logPrecision - : 1 / precision; + : 1 / multipleOf; const int = this.int({ min: min * factor, max: max * factor, diff --git a/test/modules/__snapshots__/number.spec.ts.snap b/test/modules/__snapshots__/number.spec.ts.snap index 3d10ddb4477..c04b4fe561e 100644 --- a/test/modules/__snapshots__/number.spec.ts.snap +++ b/test/modules/__snapshots__/number.spec.ts.snap @@ -26,6 +26,8 @@ exports[`number > 42 > float > with min 1`] = `-25.894775084685534`; exports[`number > 42 > float > with min and max 1`] = `-0.4260473116301`; +exports[`number > 42 > float > with min, max and multipleOf 1`] = `-0.4261`; + exports[`number > 42 > float > with min, max and precision 1`] = `-0.4261`; exports[`number > 42 > float > with plain number 1`] = `1.498160457238555`; @@ -74,6 +76,8 @@ exports[`number > 1211 > float > with min 1`] = `-2.073633389081806`; exports[`number > 1211 > float > with min and max 1`] = `61.06573706539348`; +exports[`number > 1211 > float > with min, max and multipleOf 1`] = `61.0658`; + exports[`number > 1211 > float > with min, max and precision 1`] = `61.0658`; exports[`number > 1211 > float > with plain number 1`] = `3.7140806149691343`; @@ -122,6 +126,8 @@ exports[`number > 1337 > float > with min 1`] = `-30.732938923640177`; exports[`number > 1337 > float > with min and max 1`] = `-12.915260942419991`; +exports[`number > 1337 > float > with min, max and multipleOf 1`] = `-12.9153`; + exports[`number > 1337 > float > with min, max and precision 1`] = `-12.9153`; exports[`number > 1337 > float > with plain number 1`] = `1.048098704777658`; diff --git a/test/modules/datatype.spec.ts b/test/modules/datatype.spec.ts index 3d65797d780..75f2897cf28 100644 --- a/test/modules/datatype.spec.ts +++ b/test/modules/datatype.spec.ts @@ -236,7 +236,9 @@ describe('datatype', () => { it('should throw when precision is negative', () => { expect(() => { faker.datatype.number({ precision: -0.01 }); - }).toThrow(new FakerError('Precision should be greater than 0.')); + }).toThrow( + new FakerError('multipleOf/precision should be greater than 0.') + ); }); }); @@ -327,7 +329,9 @@ describe('datatype', () => { it('should throw when precision is negative', () => { expect(() => { faker.datatype.float({ precision: -0.01 }); - }).toThrow(new FakerError('Precision should be greater than 0.')); + }).toThrow( + new FakerError('multipleOf/precision should be greater than 0.') + ); }); }); diff --git a/test/modules/number.spec.ts b/test/modules/number.spec.ts index 81a1e992c72..c61498fab91 100644 --- a/test/modules/number.spec.ts +++ b/test/modules/number.spec.ts @@ -27,6 +27,11 @@ describe('number', () => { min: -42, max: 69, precision: 0.0001, + }) + .it('with min, max and multipleOf', { + min: -42, + max: 69, + multipleOf: 0.0001, }); }); @@ -244,6 +249,22 @@ describe('number', () => { expect(results).toEqual([0, 0.5, 1, 1.5]); }); + it('provides numbers with a given multipleOf of 0.5 steps', () => { + const results = [ + ...new Set( + Array.from({ length: 50 }, () => + faker.number.float({ + min: 0, + max: 1.5, + multipleOf: 0.5, + }) + ) + ), + ].sort(); + + expect(results).toEqual([0, 0.5, 1, 1.5]); + }); + it('provides numbers with a given precision of 0.4 steps', () => { const results = [ ...new Set( @@ -292,13 +313,25 @@ describe('number', () => { it('throws an error for precision 0', () => { expect(() => faker.number.float({ precision: 0 })).toThrow( - new FakerError('Precision should be greater than 0.') + new FakerError('multipleOf/precision should be greater than 0.') + ); + }); + + it('throws an error for multipleOf 0', () => { + expect(() => faker.number.float({ multipleOf: 0 })).toThrow( + new FakerError('multipleOf/precision should be greater than 0.') ); }); it('throws an error for negative precision', () => { expect(() => faker.number.float({ precision: -0.01 })).toThrow( - new FakerError('Precision should be greater than 0.') + new FakerError('multipleOf/precision should be greater than 0.') + ); + }); + + it('throws an error for negative multipleOf', () => { + expect(() => faker.number.float({ multipleOf: -0.01 })).toThrow( + new FakerError('multipleOf/precision should be greater than 0.') ); });