-
Notifications
You must be signed in to change notification settings - Fork 57
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
+/- infinity? #53
Comments
That representation is straightforward. The harder part is defining the semantics of all the operations. For example, in general arithmetic, should we try to map numerator overflows to infinity? That may be fine for integers (denominator=1), but it's harder for other denominators. If we do overflow to infinity, should we also underflow (on denominator overflow) to zero? What about operations with infinity where floating point would give NaN? |
As a prior-art counterpoint, Python's Fraction does not support this. |
How do IEEE 754 numbers handle overflow/underflow? That is probably the way to go. As for operations that give |
That's fine as a guiding principle, but I think that will be challenging to implement, especially for generic integer types. And consider cases like The main point of
Other NaN operations off the top of my head: |
Yeah, I was really only thinking about
I agree with you, the imprecision of floating point numbers is the reason why I'm using this crate in the first place (I'm dealing with the fallout of using a library that uses floating point numbers to represent time. I'm rewriting the library, but infinity is one of my many headaches with the library).
OK, then maybe that will be a good representation? I think that as soon as you try to reduce any rational after you've done an operation, you'll end up with |
How does infinity come up in representation of time?!? I wonder if it might be better for you to wrap such values at a higher layer, like: enum Value {
Rational(BigRational),
Infinity,
} ... or whatever variants make sense in your domain. |
It's actually a really clever trick. The library is maintaining a minimum priority queue of future events sorted by date. The events themselves contain closures that are executed as they are popped off the queue. The last event is always a sentinel whose job is to go do a bunch of work before scheduling a new set of events. The issue is that events can generate more events, which all occur at a finite moment in time. So as long as events are being generated, they'll be executed before the sentinel is. The event execution system remains completely oblivious to the fact that work needs to be done by the sentinel; it just keeps executing events until there aren't any more. |
As for wrapping a BigRational, I'd rather avoid doing that as it would lead a LOT of code rewrite; either I'd have to implement the all of the standard operations over again on the wrapped value, or I'd have boatloads of match statements in the library. Convincing you about adding in infinity is easier! 😜 |
Rust is pretty good for representing such special values at the type level, rather than having to treat it as a sort-of-real numeric value. My first thought is to translate that to If you really want, you can already use |
Do comparisons count as operations? The event queue is comparing by time... |
Yes. For this, you could use a singleton wrapper
I get the humorous tone, but... it really seems like you can solve this better at a higher level. |
I suspect that you're right for this particular library. However, if we review the operations you mentioned earlier, I think that using
Other operations all require you to have a common denominator, which means that |
I believe it's possible to define semantics for everything, but I doubt that we should. |
OK, so you're against including infinity in the library? |
I'm against -- not so hard as to close this outright, but I don't think there's sufficient motivation yet. I feel if we were to add such things as infinity and NaN, we would need to be really thorough about all of the semantics and corner cases. |
I can see why you'd be against; I spent the weekend really thinking this through, especially what you said earlier:
and
The problem with what I'm proposing here is that it changes the underlying semantics of Given all this, would you be interested in a new crate that is built on |
Unfortunately, Depending on your needs and rounding semantics,
I think that sounds like a nice crate idea, but I'd rather see it developed independently. Frankly, I don't give enough time to the
I'd suggest thinking about how this will be different than a |
Yup, you're right, I missed that bound.
Did I mention that I need both
That was part of what I was wrestling with earlier today. If the At this point, I think I'm going to drop the idea of adding |
I don't have direct experience using any, but there are a few mentioned in rust-num/num#377
If "built-in precision" means they have some field specifying precision, then you could go by the rules for significant figures, which generally output the least significance among all operands. I would also treat exact rational numbers as having maximum/infinite precision. "Built-in precision" might also mean as a const generic parameter, in which case you can choose not to mix precisions at all at the type level, or else make such mixing becomes more explicit in implementations. |
That was pretty much what I was thinking, although I need to spend some more time really thinking about what this might mean in the context of non-linear functions, such as |
Is it possible to add support for +/- infinity? The rational equivalents would be logically be
1/0
and-1/0
. This would allow conversion offloat('inf')
and-float('inf')
.The text was updated successfully, but these errors were encountered: