Skip to content
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

Weights using long #14

Open
phillip-haydon opened this issue Sep 26, 2022 · 3 comments
Open

Weights using long #14

phillip-haydon opened this issue Sep 26, 2022 · 3 comments
Labels
enhancement New feature or request

Comments

@phillip-haydon
Copy link

Hey,

Is it possible to extend weights to support long, lookg like at the moment they only support int?

❤️

@ndsvw
Copy link
Owner

ndsvw commented Sep 29, 2022

Hey,

I limited the weights to int in the beginning, because Fluent Random Picker uses algorithms that sum up all the weights internally.

If the int weights are Int32.MaxValue and Int32.MaxValue, the sum can't be stored as an int. So I use long for the sum internally at the moment.

If I'd allow long weights and if they are Int64.MaxValue and Int64.MaxValue, the sum can't be stored as a long. I'd need a larger data type then internally...


2 ways are probably possible on my site:

  1. Replacing the algorithm that sums up the numbers (at least when the weights are longs) with one that works differently.
  2. .Net7 (will be available in about a month) offers a new Data type (Int128), which I could use to calculate a sum of longs. But this would only work in projects that are targeting .Net7 or higher.

Which .Net version are you targeting?

I'll take a closer look at this in the future.

@phillip-haydon
Copy link
Author

Hey,

Makes sense, you /could/ use BigInteger to sum the values. Tho it might be slow.

I'm currently targeting .net 7 rc1.

Right now I'm just casting to int so I'm not hindered, but what I'm using it for is figuring out in my game 'who' should hit.

Your library just makes mundane stuff easier :D

        var entity = Out.Of()
                         .Value(EntityType.Player).WithWeight((int)playerSpeed)
                         .AndValue(EntityType.Monster).WithWeight((int)monsterSpeed)
                         .PickOne();

@ndsvw
Copy link
Owner

ndsvw commented Oct 1, 2022

Notes for me:

  • SortingBasedWeightedLeftShuffle would break with longs because all results are 1 at some point.
Math.Pow(0.9999, 1/(double)int.MaxValue) // = 0.99999999999995348165526820594095624983310699462891
Math.Pow(0.9999, 1/(double)long.MaxValue) // = 1.00000000000000000000000000000000000000000000000000
Math.Pow(0.9999, 1/((double)long.MaxValue/10)) // = 1.00000000000000000000000000000000000000000000000000
Math.Pow(0.9999, 1/((double)long.MaxValue/1_000_000)) // = 1.00000000000000000000000000000000000000000000000000
Math.Pow(0.9999, 1/((double)long.MaxValue/10_000_000)); // = 0.99999999999999988897769753748434595763683319091797

So, maybe, there needs to be a fallback like Math.Pow(0.9999, 10_000_000/(double)n); for larger numbers.
Maybe, a fallback should already be there for ints, because for ~0,000001% of the weights (higher if we would allow long weights), it does not even make a difference, whether they are int.MaxValue or int.MaxValue / 10 (edge case):

Math.Pow(0.99999999, 1/(double)int.MaxValue) // = 1.00000000000000000000000000000000000000000000000000
Math.Pow(0.99999999, 1/((double)int.MaxValue / 10)) // = 1.00000000000000000000000000000000000000000000000000

BTW: Random.NextDouble being exactly 0 could also be problematic as the result is always 0...

  • DefaultPicker would break because it calculates the sum resulting in a possible overflow (solvable with Int128 from .Net7 or BigInteger)
  • Everything else should still work with longs.

@ndsvw ndsvw added the enhancement New feature or request label Nov 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants