Skip to content

Commit

Permalink
feat(number): add parameter fractionDigits in float (#1855)
Browse files Browse the repository at this point in the history
Co-authored-by: ST-DDT <ST-DDT@gmx.de>
  • Loading branch information
xDivisionByZerox and ST-DDT authored Jan 18, 2024
1 parent d71bc47 commit 41d8778
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/modules/finance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ export class FinanceModule extends ModuleBase {
const randValue = this.faker.number.float({
max,
min,
multipleOf: 10 ** -dec,
fractionDigits: dec,
});

const formattedString = autoFormat
Expand Down
8 changes: 4 additions & 4 deletions src/modules/location/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ export class LocationModule extends ModuleBase {

const { max = 90, min = legacyMin, precision = legacyPrecision } = options;

return this.faker.number.float({ min, max, multipleOf: 10 ** -precision });
return this.faker.number.float({ min, max, fractionDigits: precision });
}

/**
Expand Down Expand Up @@ -732,7 +732,7 @@ export class LocationModule extends ModuleBase {

const { max = 180, min = legacyMin, precision = legacyPrecision } = options;

return this.faker.number.float({ max, min, multipleOf: 10 ** -precision });
return this.faker.number.float({ max, min, fractionDigits: precision });
}

/**
Expand Down Expand Up @@ -1207,15 +1207,15 @@ export class LocationModule extends ModuleBase {

const angleRadians = this.faker.number.float({
max: 2 * Math.PI,
multipleOf: 0.00001,
fractionDigits: 5,
}); // in ° radians

const radiusMetric = isMetric ? radius : radius * 1.60934; // in km
const errorCorrection = 0.995; // avoid float issues
const distanceInKm =
this.faker.number.float({
max: radiusMetric,
multipleOf: 0.001,
fractionDigits: 3,
}) * errorCorrection; // in km

/**
Expand Down
49 changes: 43 additions & 6 deletions src/modules/number/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,26 @@ export class NumberModule extends SimpleModuleBase {
* @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.
* If `multipleOf` is passed, the upper bound is inclusive.
* This option is incompatible with the `fractionDigits` option.
* @param options.fractionDigits The maximum number of digits to appear after the decimal point.
* This option is incompatible with the `multipleOf` option.
*
* @throws When `min` is greater than `max`.
* @throws When `precision` is negative.
* @throws When `multipleOf` is negative.
* @throws When `fractionDigits` is negative.
* @throws When `fractionDigits` and `multipleOf` is passed in the same options object.
*
* @example
* faker.number.float() // 0.5688541042618454
* faker.number.float(3) // 2.367973240558058
* faker.number.float({ min: -1000000 }) //-780678.849672846
* faker.number.float({ max: 100 }) // 17.3687307164073
* faker.number.float({ multipleOf: 0.25 }) // 3.75
* faker.number.float({ min: 10, max: 100, multipleOf: 0.001 }) // 35.415
* faker.number.float({ fractionDigits: 1 }) // 0.9
* faker.number.float({ min: 10, max: 100, multipleOf: 0.02 }) // 35.42
* faker.number.float({ min: 10, max: 100, fractionDigits: 3 }) // 65.716
*
* @since 8.0.0
*/
Expand All @@ -129,6 +137,10 @@ export class NumberModule extends SimpleModuleBase {
*/
max?: number;
/**
* The number of digits to appear after the decimal point.
*/
fractionDigits?: number;
/*
* Precision of the generated number.
*
* @deprecated Use `multipleOf` instead.
Expand All @@ -147,10 +159,17 @@ export class NumberModule extends SimpleModuleBase {
};
}

// eslint-disable-next-line deprecation/deprecation
const { min = 0, max = 1, precision, multipleOf = precision } = options;
const {
min = 0,
max = 1,
fractionDigits,
precision,
multipleOf: originalMultipleOf = precision,
multipleOf = precision ??
(fractionDigits == null ? undefined : 10 ** -fractionDigits),
} = options;

if (precision !== undefined) {
if (precision != null) {
deprecated({
deprecated: 'faker.number.float({ precision })',
proposed: 'faker.number.float({ multipleOf })',
Expand All @@ -167,7 +186,25 @@ export class NumberModule extends SimpleModuleBase {
throw new FakerError(`Max ${max} should be greater than min ${min}.`);
}

if (multipleOf !== undefined) {
if (fractionDigits != null) {
if (originalMultipleOf != null) {
throw new FakerError(
'multipleOf and fractionDigits cannot be set at the same time.'
);
}

if (!Number.isInteger(fractionDigits)) {
throw new FakerError('fractionDigits should be an integer.');
}

if (fractionDigits < 0) {
throw new FakerError(
'fractionDigits should be greater than or equal to 0.'
);
}
}

if (multipleOf != null) {
if (multipleOf <= 0) {
// TODO @xDivisionByZerox: Clean up in v9.0
throw new FakerError(`multipleOf/precision should be greater than 0.`);
Expand Down
6 changes: 6 additions & 0 deletions test/modules/__snapshots__/number.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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 fractionDigits 1`] = `-0.4261`;

exports[`number > 42 > float > with min, max and multipleOf 1`] = `-0.4261`;

exports[`number > 42 > float > with min, max and precision 1`] = `-0.4261`;
Expand Down Expand Up @@ -76,6 +78,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 fractionDigits 1`] = `61.0658`;

exports[`number > 1211 > float > with min, max and multipleOf 1`] = `61.0658`;

exports[`number > 1211 > float > with min, max and precision 1`] = `61.0658`;
Expand Down Expand Up @@ -126,6 +130,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 fractionDigits 1`] = `-12.9153`;

exports[`number > 1337 > float > with min, max and multipleOf 1`] = `-12.9153`;

exports[`number > 1337 > float > with min, max and precision 1`] = `-12.9153`;
Expand Down
14 changes: 11 additions & 3 deletions test/modules/datatype.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,15 +320,23 @@ describe('datatype', () => {
const max = 9;

expect(() => {
faker.datatype.number({ min, max });
faker.datatype.float({ min, max });
}).toThrow(
new FakerError(`Max ${max} should be greater than min ${min}.`)
);
});

it('should throw when precision is negative', () => {
it('should throw when precision <= 0', () => {
const min = 1;
const max = 2;

expect(() => {
faker.datatype.float({ min, max, precision: 0 });
}).toThrow(
new FakerError('multipleOf/precision should be greater than 0.')
);
expect(() => {
faker.datatype.float({ precision: -0.01 });
faker.datatype.float({ min, max, precision: -1 });
}).toThrow(
new FakerError('multipleOf/precision should be greater than 0.')
);
Expand Down
44 changes: 44 additions & 0 deletions test/modules/number.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ describe('number', () => {
max: 69,
precision: 0.0001,
})
.it('with min, max and fractionDigits', {
min: -42,
max: 69,
fractionDigits: 4,
})
.it('with min, max and multipleOf', {
min: -42,
max: 69,
Expand Down Expand Up @@ -281,6 +286,45 @@ describe('number', () => {
expect(results).toEqual([0, 0.4, 0.8, 1.2, 1.6]);
});

it.each(times(100))(
'provides numbers with an exact fractional digits',
() => {
const actual = faker.number.float({
min: 0.5,
max: 0.99,
fractionDigits: 2,
});
expect(actual).toBe(Number(actual.toFixed(2)));
}
);

it('throws an error if fractionDigits and multipleOf is provided at the same time', () => {
expect(() =>
faker.number.float({
min: 0,
max: 10,
multipleOf: 0.25,
fractionDigits: 6,
})
).toThrow(
new FakerError(
'multipleOf and fractionDigits cannot be set at the same time.'
)
);
});

it('throws an error for non integer fractionDigits numbers', () => {
expect(() => faker.number.float({ fractionDigits: 1.337 })).toThrow(
new FakerError('fractionDigits should be an integer.')
);
});

it('throws an error for negative fractionDigits', () => {
expect(() => faker.number.float({ fractionDigits: -2 })).toThrow(
new FakerError('fractionDigits should be greater than or equal to 0.')
);
});

it('provides numbers with a given precision of 0.2', () => {
const results = [
...new Set(
Expand Down

0 comments on commit 41d8778

Please sign in to comment.