Allow specifying precision in randNumber
leon opened this issue · 6 comments
Description
in faker i used generating numbers with precision.
faker.datatype.number({ min: 100, max: 2000, precision: 100 })
which would give me
1400
Proposed solution
Could we add the precision option to randNumber?
Alternatives considered
No response
Do you want to create a pull request?
No
Hi @leon, I have attempted to add this feature in randNumber, but got stuck on one issue.
What if, the precision value is greater than provided max value, then my implementation always outputs 0
I'm not sure whether my implementation is correct (or) not. Also, Correct me if I misunderstood your use case
Check out my implementation of precision here
@Pranomvignesh Yes this what I was after :)
the new @fakerjs repo uses this code
https://github.com/faker-js/faker/blob/main/src/datatype.ts#L62-L78
There are a few workarounds in their code we might want to have as well.
You're welcome to submit a PR.
Hi @leon , Thanks for the clarification.
Upon experimenting on the new fakerjs source code, I found that it also has the flaw which I have mentioned before.
I have created some scenarios where precision will shift the output making it not compliant to the provided min and max values.
Refer the Code Sandbox Playground
import { faker } from '@faker-js/faker';
import { random } from '@ngneat/falso';
// 1. Precision > max
// Constants
let iterations = 1000;
const min = 10, max = 1000, precision = 5000
// Faker Example
const FakerOutputs = [];
const valuesNotInRangeInFaker = [];
let fakerCount = 0;
while (fakerCount++ < iterations) {
const value = faker.datatype.number({
min,
max,
precision
})
if (value < min) valuesNotInRangeInFaker.push(value);
else if (value > max) valuesNotInRangeInFaker.push(value);
FakerOutputs.push(value);
}
// Falso Example
const FalsoOutputs = [];
const valuesNotInRangeInFalso = [];
let falsoCount = 0;
// Proposed Solution
function getRandomInRange({
min = 1.0,
max = 9999.99,
fraction = 0,
precision = 1
}) {
const randNum = Number((random() * (max - min) + min).toFixed(fraction));
return Math.floor(randNum / precision) % precision;
}
while(falsoCount++ < iterations){
const value = getRandomInRange({
min,
max,
precision
})
if (value < min) valuesNotInRangeInFalso.push(value);
else if (value > max) valuesNotInRangeInFalso.push(value);
FalsoOutputs.push(value)
}
// Results
const errorPercentageInFaker = (valuesNotInRangeInFaker.length / FakerOutputs.length) * 100
const errorPercentageInFalso = (valuesNotInRangeInFalso.length / FalsoOutputs.length) * 100
console.log({
errorPercentageInFaker,
errorPercentageInFalso
})
// 2. Precision < min
// Edge Cases where precision will break the code
const edgeCases = [{
min : 4, max : 5 , precision : 3
},{
min : 8, max : 13, precision : 7
}]
edgeCases.forEach(({min,max,precision},index)=>{
console.log("Edge Case "+(index+1));
console.log("Faker", faker.datatype.number({
min,
max,
precision
}))
console.log("Falso",getRandomInRange({
min,
max,
precision
}))
})
The edgeCases here are carefully created in such a way that it will break the generator code and I believe that this won't be a practical use case for an user.
So I think, logging an error (or) warning message if the precision doesn't fall into the min-max range, would be better.
@NetanelBasal , is it advisable to add such logs in falso's functions ? Is there any recommended way of informing the user about the issue in the provided options ?