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

Infinity error - Is it really that bad? #586

Closed
Mobz87 opened this issue Jan 24, 2019 · 14 comments
Closed

Infinity error - Is it really that bad? #586

Mobz87 opened this issue Jan 24, 2019 · 14 comments

Comments

@Mobz87
Copy link

Mobz87 commented Jan 24, 2019

I might be poking to a bees nest by bringing a closed issues up again ( #502 ) but I'll take my chances.

I would like to discuss the reason way throwing an exception "just" because of Infinity.
Most of the time, If a result is Infinity it is because of a programming error (who wants an infinity results?)
It therefore make sense to tell that programmer that he has made a mistake.

But why is there no exception thrown when a double is Infinity?
Because many system, doing a iteration process, can have an infinity result doing one of the iterations and that's no problem.

By throwing an Infinity exception it forces me to have a try/catch around all my lines where I do math with UnitsNet. Infinity is a real part of my everyday life and I dont think it should throw an exception.

What do you think of doing it the same way as the double-system?
The people that has made the double-system must have had a reason not to throw an exception.
Looking forward to hear what you think!

@angularsen
Copy link
Owner

angularsen commented Jan 24, 2019

There is a discussion somewhere but I don't have the link to it right now.
Short story; Infinity only exists for double and float, but not for decimal used for some of our quantities. My argument for throwing was to have a consistent behavior. We have also discussed using generics in the future to allow consumers choose their own numeric backing type, which adds weight to the argument I think.

Does the argument make sense to you or do you see it different?

Update: The same goes for NaN.

@Mobz87
Copy link
Author

Mobz87 commented Jan 24, 2019

I make sense if some of your quantities are in decimal.
It could be nice to be able to work with Infinity again but its not the biggest problem after all

@tmilnthorp
Copy link
Collaborator

I am a bit torn. I wonder if we should allow it, similar to how we left the equality operators for double. Allow it, but put the burden on the programmer to use it appropriately.

@angularsen
Copy link
Owner

angularsen commented Jan 24, 2019

My main argument against is that it is too unpredictable that some quantities throws if you pass in NaN or Infinity, while others are fine. Also, I extremely rarely ever use NaN or Infinity for anything useful in the code I'm writing.

I don't know of any comparable types in .NET we could use as inspiration that use floating point precision, things like TimeSpan and DateTime are based on long.

This throws OverflowException: Convert.ToDecimal(float.NaN)

Assuming we had quantities with only double, we could allow NaN and Infinity, but even then, I would lean a bit against doing so just from personal preference.

@Mobz87
Copy link
Author

Mobz87 commented Jan 25, 2019

We dont like unpredictability - Either it works with Infinity or it dont, we dont like it working with half of the units :-)
My main problem is every time I divide by a unit I have to check if it is zero to avoid it throwing an exception - And I do that many time

Could we somehow make a Infinity Decimal value?

@tmilnthorp
Copy link
Collaborator

Unfortunately that's the way .NET works. Floating points divided by zero results in infinity and decimals throw an exception. It was no infinity value and just making it the max seems... Yuck.

I assume then your main issue is more that some of our types are double and some decimal. A generic type where you could specify would at least make it consistent as noted above.

@angularsen
Copy link
Owner

In my personal opinion, you should check for close-to-zero before dividing. Division by zero is overflow for most numeric types, except float/double types where they baked in the concept of infinity.

If you are truly working with infinities or say want the GUI to display Infinity automatically, then I understand it can be bothersome that Units.NET don't support it, but unless Units.NET can deliver an all-quantities-are-double implementation or we do something clever with generics and user-chose types, then I don't think we can move this along.

We do have some floating ideas about moving from struct to class to unlock the ability to use generics, so you can use Length<double> or similar. Nothing concrete yet.

Some discussion here:
#285 (comment)

@angularsen
Copy link
Owner

I'm closing this due to inactivity, please reopen if you want to discuss this further.

@senften
Copy link

senften commented Mar 29, 2019

I apologize for being late to the party. I've been meaning to add our $0.02, but, frankly, the days seem to get away from me.

The move from allowing NaN to either throwing an exception or converting to null is such a problem for us that we have elected, in the short term, to simply not move to 4.0 (This, in itself, is an issue, as well.) I will have to manage this one way or another in the near future. Staying on an unsupported release is unacceptable but managing NaN values and having those values be quantities is important to us.

I work for a small oil field service company that is monitoring real-time data off the gauges at drill sights. It is not uncommon for those sensors to drop values for any of a variety of reasons. These sampled values are not 'null'. It's not that the sample didn't occur. It's that the reading was invalid and that information and distinction is important to our analysis. Not only do I not want to check for a null every on every sample of a timeseries that could stretch weeks or months but the fact that a sample is invalid has meaning. I can't filter that out after ingest and prior to creating our quantified streams...well, I could, but then I'd drop data that important or have to deal with unquantified values.

I appreciate the desire to have all things behave and react in a similar nature, but, from a pragmatic point of view, working in C# I'm already aware of how these values behave so the idea that a decimal behaves differently than a double, while bothersome, I lay at the feet of MS and am prepared to work around it. I don't have a good workaround for all of UnitsNet not supporting NaN the way the underlying values do.

I suspect if NaN and Infinity is not supported in a coming release, we'll likely find another solution.

@tmilnthorp
Copy link
Collaborator

Thanks for your input @senften. Per above, I am in favor of adding them allowing them and letting the programmer decide how to use it (and how to handle exceptions, etc. that could arise). @angularsen?

@angularsen
Copy link
Owner

angularsen commented Mar 29, 2019 via email

@angularsen
Copy link
Owner

Just tried this:

// ArgumentException: Not a legal OleAut date.
DateTime.FromOADate(double.NaN)
DateTime.FromOADate(double.PositiveInfinity)

// ArgumentException: TimeSpan overflowed because the duration is too long.
TimeSpan.FromSeconds(double.PositiveInfinity) 
TimeSpan.FromSeconds(double.NegativeInfinity) 

// ArgumentException: TimeSpan does not accept floating point Not-a-Number values.
TimeSpan.FromSeconds(double.NaN)

It seems to me that NaN and Infinity is generally not supported in .NET's own types that closest matches Units.NET's quantity types. So I think Units.NET should also not accept NaN and Infinity to be consistent with that.

In addition, Units.NET supports decimal type for a few quantities and it would be very unpredictable if some quantities throw and some don't.

We have some loose plans to allow any numeric type via generics in the future, we could always revisit then to see if it makes sense to allow NaN/Infinity when using float or double - but I wouldn't hold my breath. We first need agree on whether to move from struct to class and that discussion is not moving along very fast.

Switching quantity to class from struct by tmilnthorp · Pull Request #500 · angularsen/UnitsNet

Create benchmarks on CPU and memory · Issue #623 · angularsen/UnitsNet

Adding benchmark project by tmilnthorp · Pull Request #637 · angularsen/UnitsNet

@senften
Copy link

senften commented Mar 30, 2019

Yes, .Net's lack of a NaT is a pain for us as well. In general, when dealing with sampled sensor data, dealing with missing or partial samples is part of every day life

As you suggest, we could wrap everything in another class. I'll have to consider how much overhead in both processing and code support that would impose.

I appreciate the quick response.

@angularsen
Copy link
Owner

Great, let me know what you find out.
For your reference, here is the Nullable<T> source code: https://referencesource.microsoft.com/mscorlib/system/nullable.cs.html

It is absolutely fast and with little overhead on its own.

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

No branches or pull requests

4 participants