ngneat / falso

All the Fake Data for All Your Real Needs 🙂

Home Page:https://ngneat.github.io/falso/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow specifying precision in randNumber

leon opened this issue · 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 ?

I submitted a PR for it 🚀
#230

Fixed by: #230