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

Best way to generate float values in range #77

Open
killercup opened this issue Mar 20, 2021 · 7 comments
Open

Best way to generate float values in range #77

killercup opened this issue Mar 20, 2021 · 7 comments
Labels

Comments

@killercup
Copy link
Member

Hi folks, in technocreatives/dbc-codegen#12 we're generating implementations of Arbitrary for structs where we know some values have to be in a specific range. For ints, this is not a problem as we just use Unstructured::int_in_range, but I'm unsure how to proceed for floats. (We currently just go with always setting the float field to the lower bound.)

My initial idea was to keep generating floats until we get one in ourr range, but that seems awfully slow. Is there a good strategy for generating floats that are in a specific range? Anything I should look up? All I can find assumes an existing random number library is in place… which I'm hesitant to add just for this.

@nagisa
Copy link
Member

nagisa commented Mar 20, 2021

I imagine the most straightforward way would probably be to generate unsigned integers and use one of the distributions to make them into a float (maybe taken from the rand crate?)

@fitzgen
Copy link
Member

fitzgen commented Mar 22, 2021

I think it would be nice to have Unstructured::float_in_range as a sibling to Unstructured::int_in_range but I am not super confident in my ability to implement this function without bias. Or -- if I am being more forgiving of myself :) -- I would have to spend a bunch of time learning more about how to do this well, and I don't have those cycles right now :)

But I agree that this functionality is desirable!

@fitzgen
Copy link
Member

fitzgen commented Mar 22, 2021

In the meantime, you can do something like this

let x: f64 = u.arbitrary()?;
// clamp `x` to `MY_MIN..=MY_MAX`
let x = min(x, MY_MAX);
let x = max(x, MY_MIN);

and ignore bias for now, instead hoping that libfuzzer will figure things out alright via its coverage feedback.

@killercup
Copy link
Member Author

killercup commented Mar 23, 2021

Thanks for the replies, Nick! I might get back to this -- right now though I've implemented it by getting a random int and scaling it. This surely has a bias but it was done in 10min and suffices for my usage for now :)

@jrmuizel
Copy link

jrmuizel commented Apr 7, 2021

What does 'unbiased' mean in this case? All floating point bit patterns between the min and max are equally likely? Or something like @killercup/rand's where the distance between each of the possible values is the same but some bit patterns are not covered.

@jrmuizel
Copy link

jrmuizel commented Apr 7, 2021

To generate all the float bit patterns you could just to_bits() the bounds, generate random ints between those integer bounds and then from_bits() back to float.

@fitzgen
Copy link
Member

fitzgen commented Apr 8, 2021

What does 'unbiased' mean in this case? All floating point bit patterns between the min and max are equally likely? Or something like @killercup/rand's where the distance between each of the possible values is the same but some bit patterns are not covered.

This is a good question, and I'm not sure which we should aim for!

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

No branches or pull requests

4 participants