Skip to content

Commit 41d8778

Browse files
feat(number): add parameter fractionDigits in float (#1855)
Co-authored-by: ST-DDT <ST-DDT@gmx.de>
1 parent d71bc47 commit 41d8778

6 files changed

Lines changed: 109 additions & 14 deletions

File tree

src/modules/finance/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ export class FinanceModule extends ModuleBase {
601601
const randValue = this.faker.number.float({
602602
max,
603603
min,
604-
multipleOf: 10 ** -dec,
604+
fractionDigits: dec,
605605
});
606606

607607
const formattedString = autoFormat

src/modules/location/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ export class LocationModule extends ModuleBase {
579579

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

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

585585
/**
@@ -732,7 +732,7 @@ export class LocationModule extends ModuleBase {
732732

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

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

738738
/**
@@ -1207,15 +1207,15 @@ export class LocationModule extends ModuleBase {
12071207

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

12131213
const radiusMetric = isMetric ? radius : radius * 1.60934; // in km
12141214
const errorCorrection = 0.995; // avoid float issues
12151215
const distanceInKm =
12161216
this.faker.number.float({
12171217
max: radiusMetric,
1218-
multipleOf: 0.001,
1218+
fractionDigits: 3,
12191219
}) * errorCorrection; // in km
12201220

12211221
/**

src/modules/number/index.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,26 @@ export class NumberModule extends SimpleModuleBase {
9797
* @param options.multipleOf The generated number will be a multiple of this property.
9898
* This property can be used to limit the result to a specific number of decimal digits.
9999
* For example `0.01` will round to 2 decimal points.
100-
* If multipleOf is passed, the upper bound is inclusive.
100+
* If `multipleOf` is passed, the upper bound is inclusive.
101+
* This option is incompatible with the `fractionDigits` option.
102+
* @param options.fractionDigits The maximum number of digits to appear after the decimal point.
103+
* This option is incompatible with the `multipleOf` option.
101104
*
102105
* @throws When `min` is greater than `max`.
103106
* @throws When `precision` is negative.
107+
* @throws When `multipleOf` is negative.
108+
* @throws When `fractionDigits` is negative.
109+
* @throws When `fractionDigits` and `multipleOf` is passed in the same options object.
104110
*
105111
* @example
106112
* faker.number.float() // 0.5688541042618454
107113
* faker.number.float(3) // 2.367973240558058
108114
* faker.number.float({ min: -1000000 }) //-780678.849672846
109115
* faker.number.float({ max: 100 }) // 17.3687307164073
110116
* faker.number.float({ multipleOf: 0.25 }) // 3.75
111-
* faker.number.float({ min: 10, max: 100, multipleOf: 0.001 }) // 35.415
117+
* faker.number.float({ fractionDigits: 1 }) // 0.9
118+
* faker.number.float({ min: 10, max: 100, multipleOf: 0.02 }) // 35.42
119+
* faker.number.float({ min: 10, max: 100, fractionDigits: 3 }) // 65.716
112120
*
113121
* @since 8.0.0
114122
*/
@@ -129,6 +137,10 @@ export class NumberModule extends SimpleModuleBase {
129137
*/
130138
max?: number;
131139
/**
140+
* The number of digits to appear after the decimal point.
141+
*/
142+
fractionDigits?: number;
143+
/*
132144
* Precision of the generated number.
133145
*
134146
* @deprecated Use `multipleOf` instead.
@@ -147,10 +159,17 @@ export class NumberModule extends SimpleModuleBase {
147159
};
148160
}
149161

150-
// eslint-disable-next-line deprecation/deprecation
151-
const { min = 0, max = 1, precision, multipleOf = precision } = options;
162+
const {
163+
min = 0,
164+
max = 1,
165+
fractionDigits,
166+
precision,
167+
multipleOf: originalMultipleOf = precision,
168+
multipleOf = precision ??
169+
(fractionDigits == null ? undefined : 10 ** -fractionDigits),
170+
} = options;
152171

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

170-
if (multipleOf !== undefined) {
189+
if (fractionDigits != null) {
190+
if (originalMultipleOf != null) {
191+
throw new FakerError(
192+
'multipleOf and fractionDigits cannot be set at the same time.'
193+
);
194+
}
195+
196+
if (!Number.isInteger(fractionDigits)) {
197+
throw new FakerError('fractionDigits should be an integer.');
198+
}
199+
200+
if (fractionDigits < 0) {
201+
throw new FakerError(
202+
'fractionDigits should be greater than or equal to 0.'
203+
);
204+
}
205+
}
206+
207+
if (multipleOf != null) {
171208
if (multipleOf <= 0) {
172209
// TODO @xDivisionByZerox: Clean up in v9.0
173210
throw new FakerError(`multipleOf/precision should be greater than 0.`);

test/modules/__snapshots__/number.spec.ts.snap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ exports[`number > 42 > float > with min 1`] = `-25.894775084685534`;
2626

2727
exports[`number > 42 > float > with min and max 1`] = `-0.4260473116301`;
2828

29+
exports[`number > 42 > float > with min, max and fractionDigits 1`] = `-0.4261`;
30+
2931
exports[`number > 42 > float > with min, max and multipleOf 1`] = `-0.4261`;
3032

3133
exports[`number > 42 > float > with min, max and precision 1`] = `-0.4261`;
@@ -76,6 +78,8 @@ exports[`number > 1211 > float > with min 1`] = `-2.073633389081806`;
7678

7779
exports[`number > 1211 > float > with min and max 1`] = `61.06573706539348`;
7880

81+
exports[`number > 1211 > float > with min, max and fractionDigits 1`] = `61.0658`;
82+
7983
exports[`number > 1211 > float > with min, max and multipleOf 1`] = `61.0658`;
8084

8185
exports[`number > 1211 > float > with min, max and precision 1`] = `61.0658`;
@@ -126,6 +130,8 @@ exports[`number > 1337 > float > with min 1`] = `-30.732938923640177`;
126130

127131
exports[`number > 1337 > float > with min and max 1`] = `-12.915260942419991`;
128132

133+
exports[`number > 1337 > float > with min, max and fractionDigits 1`] = `-12.9153`;
134+
129135
exports[`number > 1337 > float > with min, max and multipleOf 1`] = `-12.9153`;
130136

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

test/modules/datatype.spec.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,23 @@ describe('datatype', () => {
320320
const max = 9;
321321

322322
expect(() => {
323-
faker.datatype.number({ min, max });
323+
faker.datatype.float({ min, max });
324324
}).toThrow(
325325
new FakerError(`Max ${max} should be greater than min ${min}.`)
326326
);
327327
});
328328

329-
it('should throw when precision is negative', () => {
329+
it('should throw when precision <= 0', () => {
330+
const min = 1;
331+
const max = 2;
332+
333+
expect(() => {
334+
faker.datatype.float({ min, max, precision: 0 });
335+
}).toThrow(
336+
new FakerError('multipleOf/precision should be greater than 0.')
337+
);
330338
expect(() => {
331-
faker.datatype.float({ precision: -0.01 });
339+
faker.datatype.float({ min, max, precision: -1 });
332340
}).toThrow(
333341
new FakerError('multipleOf/precision should be greater than 0.')
334342
);

test/modules/number.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ describe('number', () => {
2828
max: 69,
2929
precision: 0.0001,
3030
})
31+
.it('with min, max and fractionDigits', {
32+
min: -42,
33+
max: 69,
34+
fractionDigits: 4,
35+
})
3136
.it('with min, max and multipleOf', {
3237
min: -42,
3338
max: 69,
@@ -281,6 +286,45 @@ describe('number', () => {
281286
expect(results).toEqual([0, 0.4, 0.8, 1.2, 1.6]);
282287
});
283288

289+
it.each(times(100))(
290+
'provides numbers with an exact fractional digits',
291+
() => {
292+
const actual = faker.number.float({
293+
min: 0.5,
294+
max: 0.99,
295+
fractionDigits: 2,
296+
});
297+
expect(actual).toBe(Number(actual.toFixed(2)));
298+
}
299+
);
300+
301+
it('throws an error if fractionDigits and multipleOf is provided at the same time', () => {
302+
expect(() =>
303+
faker.number.float({
304+
min: 0,
305+
max: 10,
306+
multipleOf: 0.25,
307+
fractionDigits: 6,
308+
})
309+
).toThrow(
310+
new FakerError(
311+
'multipleOf and fractionDigits cannot be set at the same time.'
312+
)
313+
);
314+
});
315+
316+
it('throws an error for non integer fractionDigits numbers', () => {
317+
expect(() => faker.number.float({ fractionDigits: 1.337 })).toThrow(
318+
new FakerError('fractionDigits should be an integer.')
319+
);
320+
});
321+
322+
it('throws an error for negative fractionDigits', () => {
323+
expect(() => faker.number.float({ fractionDigits: -2 })).toThrow(
324+
new FakerError('fractionDigits should be greater than or equal to 0.')
325+
);
326+
});
327+
284328
it('provides numbers with a given precision of 0.2', () => {
285329
const results = [
286330
...new Set(

0 commit comments

Comments
 (0)