Skip to content

Resolve #81 to deal with a potential future scenario of PRNG generating 1 #120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

darrelfrancis
Copy link

@darrelfrancis darrelfrancis commented Apr 2, 2025

Hi @j0pgrm, re #81

Your if statement is there to cover the possbility that your PRNG will generate the number 1. In general, PRNGs produce values from 0 to less than 1, i.e. from the range 0 (inclusive) to 1 (exclusive). This is because when they generate an N-bit binary fraction, the highest value (all 1s) will be just a tiny bit smaller than 1.

Your Math.floor correctly rounds downward, so that rand will be in the range 0 (inclusive) to ENCODING_LEN - 1 (inclusive). So the if is never triggered.

If, for some reason, you in future switch to a prng that somehow can generate a 1, for example because it has an idiosyncratic desire to cover a range of 0 (exclusive) to 1 (inclusive), then:

  • the chance of this is extremely small (1 in 2^N, not 1 in 2^8)
  • the PRNG will have lost the ability to generate 0
  • your random character generator would have a micrscopically smaller chance of generating the first encoding character, and have a microscopic chance of trying to pick the non-existent character at #ENCODING_LEN.

A neat solution for you is to simply wrap round that exactly-1 PRNG value back to 0. A simple way to achieve this is to modulo the rand by ENCODING_LEN.

Thank you for an excellent library.

Hi @j0pgrm, re ulid#81

Your `if` statement is there to cover the possbility that your PRNG will generate the number 1. 
In general, PRNGs produce values from 0 to _less than_ 1, i.e. from the range 0 (inclusive) to 1 (exclusive). This is because when they generate an N-bit binary fraction, the highest value (all `1`s) will be just a tiny bit smaller than 1.

Your `Math.floor` correctly rounds downward, so that `rand` will be in the range 0 (inclusive) to ENCODING_LEN *- 1* (inclusive). 
So the `if` will never be triggered.

If, for some reason, you in future switch to a prng that somehow can generate a 1, for example because it has an idiosyncratic desire to cover a range of 0 (_exclusive_) to 1 (_inclusive_), then:

* the chance of this is extremely small (1 in 2**N, not 1 in 2**8)
* the PRNG will have lost the ability to generate 0
* your random character generator would have a micrscopically smaller chance of generating the first encoding character, and have a microscopic chance of trying to pick the non-existent character at #ENCODING_LEN.

A neat solution for you is to simply wrap round that exactly-1 PRNG value back to 0, most conveniently  A simple way to achieve this is to modulo the `rand` by ENCODING_LEN.



Thank you for an excellent library.
@darrelfrancis darrelfrancis changed the title Update utils.ts Resolve #81 to deal with a potential future scenario of PRNG generating 1 Apr 2, 2025
@perry-mitchell
Copy link
Member

Hi @darrelfrancis! Apologies for not getting to this sooner. Your logic makes sense and the PR looks good imo, but I'd like the tests to run before considering a merge. For some reason they haven't run - I'll try to check that first, and simply run manually in your PR if I can't figure it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants