-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Range is odd when used with floating point types #17010
Comments
It should just be ported to used a trait with successor / predecessor instead of addition. This would also allow it to work with |
I disagree. I think this is almost never what you want. Usually you want some finite step size. Using multiplication instead of addition fixes the rounding errors. |
@vks: It doesn't matter if it's almost never what you want for floating point types, it's the sane definition of the basic generic |
It's worth noting that there aren't any rounding error per se; multiplication would only help as long as you were using a datatype that could hold the required precision. Consider instead And then instead of multiplication you might as well just cast to the float. |
@thestinger That is not what @Veedrac I'm not sure I understand. How is I still think multiplication would solve all the issues you mentioned, because it would yield exactly the expected number of elements (even if some are identical do to lacking precision). |
@vks So you have |
@vks: The only reason that |
@Veedrac I think I understand your point now. The problem seems to be the implementation of
Really? That surprises me.
Currently it is only defined for types that implement I'm not convinced that it should be generalized to types that don't implement If it is decided to implement it using some kind of successor trait, then I think it should not be implemented for floating point numbers (unless the "successor" of a float x is defined as x + 1). |
Python only has an equivalent to |
About how to fix this issue:
(I would favor 2. or 3.) Edit: @thestinger I removed the paragraph about Python's range, because it was talking past each other.
I don't know what the intention was when |
Instead of |
It's not going to optimize out for big integers, and might not optimize out for primitive integers. |
This is a good idea. It does not really matter whether it optimizes out, because it is only done once. (You don't call |
Code size does matter, and making the loop end condition more complex is going to make it harder for LLVM to optimize it down to the same code as the equivalent C loop. |
The loop would be the same; it's just the creation of the range that would have the check. In other words, it would go here: https://github.com/rust-lang/rust/blob/master/src/libcore/iter.rs#L1952. |
I also don't see how that assertion might affect the loop. I could imagine that it leads to problems when nesting loops though. At the very least the wrong size hint should be fixed (see 4.). |
Note also that the Personally I prefer putting it in the constructor because I feel it should optimise out in the case that I care about (primitive integers) and the other cases are very unlikely to be bottlenecks. In other words, I want to support:
as construction times could (in theory) matter, but any case with big integers, floats or similar probably won't ever occur in a similar context. |
`size_hint` was implicitly assuming that for `t: T` the following holds: t + One::one() != t This is not true, i.e. if `T` is a float. Due to this fact, `range` can return an infinite iterator. However, `size_hint` would always claim the iterator is finite. This commit fixes `size_hint` by not specifying an upper bound. Updates rust-lang#17010.
A little problem of (That's why I did not use it in my branch that fixes the size hint.) |
You can use But we would then also have the problem where we aren't rounding intelligently, such as with
giving
so the problem is more systemic than I thought. |
gives
Since floats seem to also have an improper minimum size for their hint, I'm starting to doubt whether supporting |
I'm fine with not supporting float ranges (don't think that this is used anyway). Note that for float ranges you often want non-integer step sizes. For floats you want to use something like numpy's >>> linspace(start=2.0, stop=3.0, num=5)
array([ 2. , 2.25, 2.5 , 2.75, 3. ]) (The point is that it guarantees you to get exactly |
This brings us back to
I don't think anyone is in favour doing nothing, but I wouldn't know which of the first two is best. A trait would be possibly more extensible to other types but it might just be pointless overhead if it's never used. |
Naively I would assume that the compiler can optimize away the successor abstraction. If not, I think implementing |
Sorry, I meant implementation overhead. If the only things usable in |
A trait for enumerated types is useful beyond |
A |
I think we should implement Alternatively, the size hint should only be implemented for integers. |
|
…ykril Add `toggle_async_sugar` assist code action Implement code action for sugaring and de-sugaring asynchronous functions. This code action does not import `Future` trait when de-sugaring and does not touch function boby, I guess this can be implemented later if needed. This action also does not take into consideration other bounds because IMO it's usually "let me try to use sugared version here". Feel free to request changes, that's my first code action implementation 😄 Closes rust-lang#17010 Relates to rust-lang#16195
For one,
outputs
min: 1e8 ≤ length: 1e9 ≤ max: 1e8
.There's no real decision about what to do when rounding errors means
r.next() == r.next()
, such as with:which currently results in an infinite iterator.
Personally I don't see a big problem with it, but unless floating ranges are banned it should at least avoid breaking
size_hint
.Edit:
Further, rounding currently means that the size hints can be wrong. Both the upper bound:
and the lower bound:
The text was updated successfully, but these errors were encountered: