Are .NET Decimal type computations deterministic?
Asked Answered
P

1

9

I have two questions regarding .NET's decimal data type determinism:

  1. Are decimal type computations cross-platform deterministic? Or in other words, will math operations on decimal type produce exactly the same results on all platforms?

  2. Is casting decimal number to float or double cross-platform deterministic (casts will always produce exactly the same result)?

Pyrology answered 6/9, 2016 at 9:13 Comment(7)
I wouldn't be at all surprised to see some differences in corner cases between Mono and the Microsoft implementations...Contumacy
Indeed, there was a bug in the Mono implementation that caused different results compared to the Windows one. I would expect others.Eolithic
As far as I know, the answers to both questions could be yes. No guarantee. However, there is an issue with conversion to double in relation to trailing zeroes of the decimal. It is possible to have two decimal values that only differ by the number of trailing zeroes, and therefore these two decimals are considered equal (even if they have distinct internal representations), such that when you convert them to double, the resulting double values are distinct. Addition: This also proves that the conversion to double does not always pick the nearest destination. Want example?Jalisajalisco
It would indeed be good to see an example: that doesn't sound right to me.Sicken
@Sicken An example: var a = ((double)200.000000000000000000000M).ToString("R"); var b = ((double)200.0000000000000000000000M).ToString("R"); var c = ((double)200.00000000000000000000000M).ToString("R");. Taken from late answer here. Because the System.Decimal implementation of GetHashCode() works by first converting to double and then truncating that double a bit, the decimal involved in a here even has the wrong decimal.GetHashCode(). The other two have the right hash code.Jalisajalisco
Not what I was hoping for. So custom numeric data type is the only way to get cross-platform deterministic computations that have numbers with fractional part in .NET. Reinventing the wheel for all non-basic math operations that go with that custom data type is the tougher part I think.Pyrology
I guess, apart from bugs, decimals should be deterministic, since they are implemented in .NET, floats and doubles are probably not, because they are computed on the CPU (which is at best following an standard). Casts involve both and I wouldn't expect them to be deterministic.Mccallion
T
0

There's a lot of fear-mongering in the comments to this question.

First, there's the fear of a certain Mono bug sometime in the past. Not only has that been already fixed, but just don't use Mono in 2021. Both .Net Core and .Net5 are fully cross-platform.

Then there's the fear that GetHashCode can return equal values for non-equal decimal instances. Yes, that's how GetHashCode (and indeed, all hash functions) work, otherwise you could compress any arbitrary data type to 4 bytes. Instead of typing all that, I recommend reading a book on hashing.

To the OP, there's no need to either listen to those people or reinvent decimal. It's perfectly safe to use.

Tonkin answered 18/3, 2021 at 16:0 Comment(2)
GetHashCode can return true for non-equal decimal instances no need to rephrase. Re-read?Tonkin
Okay fine, hopefully that clarification helps OP understand the state of decimal better.Tonkin

© 2022 - 2024 — McMap. All rights reserved.