Skip to content

Conversation

@darrelfrancis
Copy link
Contributor

@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.

Copy link

@cyber-hari cyber-hari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@perry-mitchell perry-mitchell merged commit 63784e2 into ulid:master Jun 8, 2025
3 of 4 checks passed
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.

3 participants