aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/guide/upgrading.md19
-rw-r--r--src/internal/mersenne/mersenne.ts14
-rw-r--r--src/modules/color/index.ts8
-rw-r--r--src/modules/number/index.ts38
-rw-r--r--test/__snapshots__/datatype.spec.ts.snap6
-rw-r--r--test/__snapshots__/finance.spec.ts.snap4
-rw-r--r--test/__snapshots__/mersenne.spec.ts.snap36
-rw-r--r--test/__snapshots__/number.spec.ts.snap24
-rw-r--r--test/mersenne.spec.ts26
-rw-r--r--test/number.spec.ts17
10 files changed, 88 insertions, 104 deletions
diff --git a/docs/guide/upgrading.md b/docs/guide/upgrading.md
index c30ee63b..673ab610 100644
--- a/docs/guide/upgrading.md
+++ b/docs/guide/upgrading.md
@@ -103,11 +103,20 @@ The `faker.address.*` methods will continue to work as an alias in v8 and v9, bu
The number-related methods previously found in `faker.datatype` have been moved to a new `faker.number` module.
For the old `faker.datatype.number` method you should replace with `faker.number.int` or `faker.number.float` depending on the precision required.
- faker.datatype.number() //35
- faker.datatype.int() //35
-
- faker.datatype.number({precision:0.01}) //35.21
- faker.datatype.float({precision:0.01}) //35.21
+By default, `faker.number.float` no longer defaults to a precision of 0.01
+
+```js
+// OLD
+faker.datatype.number({ max: 100 }); // 35
+faker.datatype.number({ max: 100, precision: 0.01 }); // 35.21
+faker.datatype.float({ max: 100 }); // 35.21
+faker.datatype.float({ max: 100, precision: 0.001 }); // 35.211
+
+// NEW
+faker.number.int({ max: 100 }); // 35
+faker.number.float({ max: 100 }); // 35.21092065742612
+faker.number.float({ max: 100, precision: 0.01 }); // 35.21
+```
| Old method | New method |
| ----------------------- | ------------------------------------------ |
diff --git a/src/internal/mersenne/mersenne.ts b/src/internal/mersenne/mersenne.ts
index e7c0355c..c823af7e 100644
--- a/src/internal/mersenne/mersenne.ts
+++ b/src/internal/mersenne/mersenne.ts
@@ -7,13 +7,10 @@ import Twister from './twister';
*/
export interface Mersenne {
/**
- * Generates a random number between `[min, max)`. The result is already floored.
- *
- * @param options The options to generate a random number.
- * @param options.min The minimum number.
- * @param options.max The maximum number.
+ * Generates a random float between `[0, 1)`.
+ * This method is called `next` so that it could be used as an [iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol)
*/
- next(options: { max: number; min: number }): number;
+ next(): number;
/**
* Sets the seed to use.
@@ -34,10 +31,9 @@ export default function mersenne(): Mersenne {
twister.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER));
return {
- next({ min, max }): number {
- return Math.floor(twister.genrandReal2() * (max - min) + min);
+ next(): number {
+ return twister.genrandReal2();
},
-
seed(seed: number | number[]): void {
if (typeof seed === 'number') {
twister.initGenrand(seed);
diff --git a/src/modules/color/index.ts b/src/modules/color/index.ts
index 9831d258..981dae60 100644
--- a/src/modules/color/index.ts
+++ b/src/modules/color/index.ts
@@ -377,7 +377,7 @@ export class ColorModule {
color = Array.from({ length: 3 }, () => this.faker.number.int(255));
if (includeAlpha) {
- color.push(this.faker.number.float());
+ color.push(this.faker.number.float({ precision: 0.01 }));
cssFunction = 'rgba';
}
@@ -458,7 +458,7 @@ export class ColorModule {
}): string | number[];
cmyk(options?: { format?: ColorFormat }): string | number[] {
const color: string | number[] = Array.from({ length: 4 }, () =>
- this.faker.number.float()
+ this.faker.number.float({ precision: 0.01 })
);
return toColorFormat(color, options?.format || 'decimal', 'cmyk');
}
@@ -568,7 +568,7 @@ export class ColorModule {
}): 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());
+ hsl.push(this.faker.number.float({ precision: 0.01 }));
}
return toColorFormat(
@@ -674,7 +674,7 @@ export class ColorModule {
}): string | number[] {
const hsl: number[] = [this.faker.number.int(360)];
for (let i = 0; i < 2; i++) {
- hsl.push(this.faker.number.float());
+ hsl.push(this.faker.number.float({ precision: 0.01 }));
}
return toColorFormat(hsl, options?.format || 'decimal', 'hwb');
diff --git a/src/modules/number/index.ts b/src/modules/number/index.ts
index 13368990..96e5067d 100644
--- a/src/modules/number/index.ts
+++ b/src/modules/number/index.ts
@@ -81,8 +81,8 @@ export class NumberModule {
const mersenne: Mersenne =
// @ts-expect-error: access private member field
this.faker._mersenne;
-
- return mersenne.next({ min: effectiveMin, max: effectiveMax + 1 });
+ const real = mersenne.next();
+ return Math.floor(real * (effectiveMax + 1 - effectiveMin) + effectiveMin);
}
/**
@@ -91,13 +91,13 @@ export class NumberModule {
* @param options Upper bound or options object. Defaults to `{}`.
* @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. Defaults to `0.01`.
+ * @param options.precision Precision of the generated number, for example `0.01` will round to 2 decimal points.
*
* @example
- * faker.number.float() // 0.89
- * faker.number.float(3) // 1.14
- * faker.number.float({ min: -1000000 }) // -823469.91
- * faker.number.float({ max: 100 }) // 27.28
+ * 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({ precision: 0.1 }) // 0.9
* faker.number.float({ min: 10, max: 100, precision: 0.001 }) // 35.415
*
@@ -133,7 +133,7 @@ export class NumberModule {
};
}
- const { min = 0, max = 1, precision = 0.01 } = options;
+ const { min = 0, max = 1, precision } = options;
if (max === min) {
return min;
@@ -143,13 +143,23 @@ export class NumberModule {
throw new FakerError(`Max ${max} should be greater than min ${min}.`);
}
- const factor = 1 / precision;
- const int = this.int({
- min: min * factor,
- max: max * factor,
- });
+ if (precision !== undefined) {
+ if (precision <= 0) {
+ throw new FakerError(`Precision should be greater than 0.`);
+ }
- return int / factor;
+ const factor = 1 / precision;
+ const int = this.int({
+ min: min * factor,
+ max: max * factor,
+ });
+ return int / factor;
+ } else {
+ // @ts-expect-error: access private member field
+ const mersenne: Mersenne = this.faker._mersenne;
+ const real = mersenne.next();
+ return real * (max - min) + min;
+ }
}
/**
diff --git a/test/__snapshots__/datatype.spec.ts.snap b/test/__snapshots__/datatype.spec.ts.snap
index b4dae898..eece8554 100644
--- a/test/__snapshots__/datatype.spec.ts.snap
+++ b/test/__snapshots__/datatype.spec.ts.snap
@@ -267,8 +267,8 @@ exports[`datatype > 1337 > array > noArgs 1`] = `
"e|/Jqjjj!B",
"GDWQgC2M;q",
3648103756333056,
- 3967686428065792,
- ".Gm3tRwnZ2",
+ "I1.Gm3tRwn",
+ 1668592164667392,
8623125245722624,
3831794621218816,
]
@@ -351,7 +351,7 @@ exports[`datatype > 1337 > hexadecimal > with length, prefix, and casing 1`] = `
exports[`datatype > 1337 > hexadecimal > with prefix 1`] = `"0x5"`;
-exports[`datatype > 1337 > json 1`] = `"{\\"foo\\":\\"U/4:SK$>6Q\\",\\"bar\\":2359372120326144,\\"bike\\":\\"{:e=+kD)[B\\",\\"a\\":\\"e|/Jqjjj!B\\",\\"b\\":\\"GDWQgC2M;q\\",\\"name\\":3648103756333056,\\"prop\\":3967686428065792}"`;
+exports[`datatype > 1337 > json 1`] = `"{\\"foo\\":\\"U/4:SK$>6Q\\",\\"bar\\":2359372120326144,\\"bike\\":\\"{:e=+kD)[B\\",\\"a\\":\\"e|/Jqjjj!B\\",\\"b\\":\\"GDWQgC2M;q\\",\\"name\\":3648103756333056,\\"prop\\":\\"I1.Gm3tRwn\\"}"`;
exports[`datatype > 1337 > number > noArgs 1`] = `26202`;
diff --git a/test/__snapshots__/finance.spec.ts.snap b/test/__snapshots__/finance.spec.ts.snap
index 95fa5c26..937b84ef 100644
--- a/test/__snapshots__/finance.spec.ts.snap
+++ b/test/__snapshots__/finance.spec.ts.snap
@@ -38,9 +38,9 @@ exports[`finance > 42 > currencySymbol 1`] = `"₱"`;
exports[`finance > 42 > ethereumAddress 1`] = `"0x8be4abdd39321ad7d3fe01ffce404f4d6db0906b"`;
-exports[`finance > 42 > iban > noArgs 1`] = `"GT30Y75110867098F1E3542612J4"`;
+exports[`finance > 42 > iban > noArgs 1`] = `"GT03975110867098F1E3542612J4"`;
-exports[`finance > 42 > iban > with formatted 1`] = `"GT30 Y751 1086 7098 F1E3 5426 12J4"`;
+exports[`finance > 42 > iban > with formatted 1`] = `"GT03 9751 1086 7098 F1E3 5426 12J4"`;
exports[`finance > 42 > iban > with formatted and countryCode 1`] = `"DE47 7175 0020 0086 0600 97"`;
diff --git a/test/__snapshots__/mersenne.spec.ts.snap b/test/__snapshots__/mersenne.spec.ts.snap
index 21d3e4cc..08002528 100644
--- a/test/__snapshots__/mersenne.spec.ts.snap
+++ b/test/__snapshots__/mersenne.spec.ts.snap
@@ -1,37 +1,13 @@
// Vitest Snapshot v1
-exports[`mersenne twister > seed: [42,1,2] > should return deterministic values for next({ min: -50, max: 60 }) 1`] = `44`;
+exports[`mersenne twister > seed: [42,1,2] > should return deterministic value for next() 1`] = `0.8562037434894592`;
-exports[`mersenne twister > seed: [42,1,2] > should return deterministic values for next({ min: -60, max: 0 }) 1`] = `-9`;
+exports[`mersenne twister > seed: [1211,1,2] > should return deterministic value for next() 1`] = `0.8916433283593506`;
-exports[`mersenne twister > seed: [42,1,2] > should return deterministic values for next({ min: 0, max: 100 }) 1`] = `85`;
+exports[`mersenne twister > seed: [1337,1,2] > should return deterministic value for next() 1`] = `0.17990487208589911`;
-exports[`mersenne twister > seed: [1211,1,2] > should return deterministic values for next({ min: -50, max: 60 }) 1`] = `48`;
+exports[`mersenne twister > seed: 42 > should return deterministic value for next() 1`] = `0.37454011430963874`;
-exports[`mersenne twister > seed: [1211,1,2] > should return deterministic values for next({ min: -60, max: 0 }) 1`] = `-7`;
+exports[`mersenne twister > seed: 1211 > should return deterministic value for next() 1`] = `0.9285201537422836`;
-exports[`mersenne twister > seed: [1211,1,2] > should return deterministic values for next({ min: 0, max: 100 }) 1`] = `89`;
-
-exports[`mersenne twister > seed: [1337,1,2] > should return deterministic values for next({ min: -50, max: 60 }) 1`] = `-31`;
-
-exports[`mersenne twister > seed: [1337,1,2] > should return deterministic values for next({ min: -60, max: 0 }) 1`] = `-50`;
-
-exports[`mersenne twister > seed: [1337,1,2] > should return deterministic values for next({ min: 0, max: 100 }) 1`] = `17`;
-
-exports[`mersenne twister > seed: 42 > should return deterministic values for next({ min: -50, max: 60 }) 1`] = `-9`;
-
-exports[`mersenne twister > seed: 42 > should return deterministic values for next({ min: -60, max: 0 }) 1`] = `-38`;
-
-exports[`mersenne twister > seed: 42 > should return deterministic values for next({ min: 0, max: 100 }) 1`] = `37`;
-
-exports[`mersenne twister > seed: 1211 > should return deterministic values for next({ min: -50, max: 60 }) 1`] = `52`;
-
-exports[`mersenne twister > seed: 1211 > should return deterministic values for next({ min: -60, max: 0 }) 1`] = `-5`;
-
-exports[`mersenne twister > seed: 1211 > should return deterministic values for next({ min: 0, max: 100 }) 1`] = `92`;
-
-exports[`mersenne twister > seed: 1337 > should return deterministic values for next({ min: -50, max: 60 }) 1`] = `-22`;
-
-exports[`mersenne twister > seed: 1337 > should return deterministic values for next({ min: -60, max: 0 }) 1`] = `-45`;
-
-exports[`mersenne twister > seed: 1337 > should return deterministic values for next({ min: 0, max: 100 }) 1`] = `26`;
+exports[`mersenne twister > seed: 1337 > should return deterministic value for next() 1`] = `0.2620246761944145`;
diff --git a/test/__snapshots__/number.spec.ts.snap b/test/__snapshots__/number.spec.ts.snap
index e699dc95..71523ecf 100644
--- a/test/__snapshots__/number.spec.ts.snap
+++ b/test/__snapshots__/number.spec.ts.snap
@@ -20,15 +20,15 @@ exports[`number > 42 > binary > with options 1`] = `"100"`;
exports[`number > 42 > binary > with value 1`] = `"0"`;
-exports[`number > 42 > float > with max 1`] = `25.84`;
+exports[`number > 42 > float > with max 1`] = `25.843267887365073`;
-exports[`number > 42 > float > with min 1`] = `-25.9`;
+exports[`number > 42 > float > with min 1`] = `-25.894775084685534`;
-exports[`number > 42 > float > with min and max 1`] = `-0.43`;
+exports[`number > 42 > float > with min and max 1`] = `-0.4260473116301`;
exports[`number > 42 > float > with min, max and precision 1`] = `-0.4261`;
-exports[`number > 42 > float > with plain number 1`] = `1.5`;
+exports[`number > 42 > float > with plain number 1`] = `1.498160457238555`;
exports[`number > 42 > hex > noArgs 1`] = `"5"`;
@@ -68,15 +68,15 @@ exports[`number > 1211 > binary > with options 1`] = `"1010"`;
exports[`number > 1211 > binary > with value 1`] = `"1"`;
-exports[`number > 1211 > float > with max 1`] = `64.07`;
+exports[`number > 1211 > float > with max 1`] = `64.06789060821757`;
-exports[`number > 1211 > float > with min 1`] = `-2.07`;
+exports[`number > 1211 > float > with min 1`] = `-2.073633389081806`;
-exports[`number > 1211 > float > with min and max 1`] = `61.07`;
+exports[`number > 1211 > float > with min and max 1`] = `61.06573706539348`;
exports[`number > 1211 > float > with min, max and precision 1`] = `61.0658`;
-exports[`number > 1211 > float > with plain number 1`] = `3.72`;
+exports[`number > 1211 > float > with plain number 1`] = `3.7140806149691343`;
exports[`number > 1211 > hex > noArgs 1`] = `"e"`;
@@ -116,15 +116,15 @@ exports[`number > 1337 > binary > with options 1`] = `"10"`;
exports[`number > 1337 > binary > with value 1`] = `"0"`;
-exports[`number > 1337 > float > with max 1`] = `18.08`;
+exports[`number > 1337 > float > with max 1`] = `18.0797026574146`;
-exports[`number > 1337 > float > with min 1`] = `-30.74`;
+exports[`number > 1337 > float > with min 1`] = `-30.732938923640177`;
-exports[`number > 1337 > float > with min and max 1`] = `-12.92`;
+exports[`number > 1337 > float > with min and max 1`] = `-12.915260942419991`;
exports[`number > 1337 > float > with min, max and precision 1`] = `-12.9153`;
-exports[`number > 1337 > float > with plain number 1`] = `1.05`;
+exports[`number > 1337 > float > with plain number 1`] = `1.048098704777658`;
exports[`number > 1337 > hex > noArgs 1`] = `"4"`;
diff --git a/test/mersenne.spec.ts b/test/mersenne.spec.ts
index f6585783..d495804c 100644
--- a/test/mersenne.spec.ts
+++ b/test/mersenne.spec.ts
@@ -3,12 +3,6 @@ import type { Mersenne } from '../src/internal/mersenne/mersenne';
import mersenneFn from '../src/internal/mersenne/mersenne';
import { seededRuns } from './support/seededRuns';
-const minMaxTestCases = [
- { min: 0, max: 100 },
- { min: -60, max: 0 },
- { min: -50, max: 60 },
-];
-
const NON_SEEDED_BASED_RUN = 25;
describe('mersenne twister', () => {
@@ -24,18 +18,10 @@ describe('mersenne twister', () => {
mersenne.seed(seed);
});
- for (const { min, max } of minMaxTestCases) {
- it(`should return deterministic values for next({ min: ${min}, max: ${max} })`, () => {
- const actual = mersenne.next({ min, max });
-
- expect(actual).toMatchSnapshot();
- });
- }
-
- it.todo(`should return 0 for next({ min: ${0}, max: ${1} })`, () => {
- const actual = mersenne.next({ min: 0, max: 1 });
+ it(`should return deterministic value for next()`, () => {
+ const actual = mersenne.next();
- expect(actual).toEqual(0);
+ expect(actual).toMatchSnapshot();
});
});
}
@@ -57,11 +43,11 @@ describe('mersenne twister', () => {
for (let i = 1; i <= NON_SEEDED_BASED_RUN; i++) {
describe('next', () => {
- it('should return random number from interval [min, max)', () => {
- const actual = mersenne.next({ min: 0, max: 2 });
+ it('should return random number from interval [0, 1)', () => {
+ const actual = mersenne.next();
expect(actual).toBeGreaterThanOrEqual(0);
- expect(actual).toBeLessThan(2);
+ expect(actual).toBeLessThan(1);
});
});
}
diff --git a/test/number.spec.ts b/test/number.spec.ts
index 91208e00..78a385b9 100644
--- a/test/number.spec.ts
+++ b/test/number.spec.ts
@@ -142,9 +142,10 @@ describe('number', () => {
});
describe('float', () => {
- it('should return a random float with a default precision of 2 digits after floating point', () => {
+ it('should return a random float', () => {
const actual = faker.number.float();
- expect(actual).toBe(Number(actual.toFixed(2)));
+ expect(actual).toBeGreaterThanOrEqual(0);
+ expect(actual).toBeLessThanOrEqual(1);
});
it('should return a random float with given max', () => {
@@ -220,10 +221,16 @@ describe('number', () => {
}
});
- it('provides number with a precision 0', () => {
- const actual = faker.number.float({ precision: 0 });
+ it('throws an error for precision 0', () => {
+ expect(() => faker.number.float({ precision: 0 })).toThrowError(
+ new FakerError('Precision should be greater than 0.')
+ );
+ });
- expect(actual).toBe(Math.floor(actual));
+ it('throws an error for negative precision', () => {
+ expect(() => faker.number.float({ precision: -0.01 })).toThrowError(
+ new FakerError('Precision should be greater than 0.')
+ );
});
it('should not modify the input object', () => {