C# Compare two double with .Equals() - c#

I use ReShaper and when I compare two double values with ==, it suggests that I should use the Math. ABS method with a tolerance. See: https://www.jetbrains.com/help/resharper/2016.2/CompareOfFloatsByEqualityOperator.html
This example
double d = 0.0;
double d2 = 0.0;
if (d == d2)
{
/* some code */
}
is then converted to
double d = 0.0;
double d2 = 0.0;
if (Math.Abs(d - d2) < TOLERANCE)
{
/* some code */
}
But I think it's really complicated for a developer to think about the right tolerance. So I thought this may be implemented in the Double.Equals() method.
But this method is implemented like so
public override bool Equals(Object obj) {
if (!(obj is Double)) {
return false;
}
double temp = ((Double)obj).m_value;
// This code below is written this way for performance reasons i.e the != and == check is intentional.
if (temp == m_value) {
return true;
}
return IsNaN(temp) && IsNaN(m_value);
}
public bool Equals(Double obj)
{
if (obj == m_value) {
return true;
}
return IsNaN(obj) && IsNaN(m_value);
}
Why is that? And what is the correct way to compare double values?

You could create an extension method
public static class DoubleExtension
{
public static bool AlmostEqualTo(this double value1, double value2)
{
return Math.Abs(value1 - value2) < 0.0000001;
}
}
And use it like this
doubleValue.AlmostEqualTo(doubleValue2)

https://learn.microsoft.com/en-us/dotnet/api/system.numerics.complex.equals?view=net-6.0
If the obj parameter is not a Complex object, but it is a data type
for which an implicit conversion is defined, the Equals(Object) method
converts obj to a Complex object whose real part is equal to the value
of obj and whose imaginary part is equal to zero before it performs
the comparison. The following example illustrates this by finding that
a complex number and a double-precision floating-point value are
equal.
double n1 = 16.33;
System.Numerics.Complex c1 =
new System.Numerics.Complex(16.33, 0);
Console.WriteLine(c1.Equals(n1)); // Returns true.

I ended up using
double piConstant = 3.142;
double piFractional = 7/22;
if(piConstatnt.String("{0:0.00}")==piFractional.String("{0:0.00}")
{
// some code
}
This lets me control the precision by setting the desired string format.
https://www.csharp-examples.net/string-format-double/
In case you want more info on Equals method from microsoft.
https://learn.microsoft.com/en-us/dotnet/api/system.double.equals?view=net-5.0

Related

When the int variable is more than 10 digits

When the int variable is more than 10 digits, an error occurs and the number becomes negative.
Why is this happening and how can I solve the problem?
This is my code:
UnityWebRequest www = new UnityWebRequest("https://api.hypixel.net/skyblock/bazaar");
www.downloadHandler = new DownloadHandlerBuffer();
yield return www.SendWebRequest();
JSONNode itemsData = JSON.Parse(www.downloadHandler.text);
unixtimeOnline = itemsData2["lastUpdated"];
Debug.Log(unixtimeOnline);
// output -2147483648
tl;dr
Simply use ulong instead of int for unixtimeOnline
ulong unixtimeOnline = itemsData2["lastUpdated"];
What happened?
As was already mentioned int (or also System.Int32) has 32 bits.
The int.MaxValue is
2147483647
no int can be higher than that. What you get is basically a byte overflow.
From the JSON.Parse I suspect you are using SimpleJson
and if you have
int unixtimeOnline = itemsData2["lastUpdated"];
it will implicitly use
public static implicit operator int(JSONNode d)
{
return (d == null) ? 0 : d.AsInt;
}
which uses AsInt
public virtual int AsInt
{
get { return (int)AsDouble; }
set { AsDouble = value; }
}
which is a problem because a double can hold up to
so when you simply do
double d = 2147483648.0;
int example = (int)d;
you will again get
-2147483648
What you want
You want to use a type that supports larger numbers. Like e.g.
long: goes up to
9,223,372,036,854,775,807
and is actually what system time ticks are usually stored as (see e.g. DateTime.Ticks
or actually since your time is probably never negative anyway directly use the unsigned ones
ulong: goes up to
18,446,744,073,709,551,615
Solution
Long store short: There are implicit conversion for the other numeric values so all you need to do is use
ulong unixtimeOnline = itemsData2["lastUpdated"];
and it will use AsUlong instead
public static implicit operator ulong(JSONNode d)
{
return (d == null) ? 0 : d.AsULong;
}
which now correctly uses
public virtual ulong AsULong
{
get
{
ulong val = 0;
if (ulong.TryParse(Value, out val))
return val;
return 0;
}
set
{
Value = value.ToString();
}
}
As the comment says you will need to use a long variable type

How to get an exception on inaccurate calculation?

Every time we need a high decimal-precision, we use decimals to do the calculations. Is there any way to check if the precision did suffice for the calculation?
I would like to make the following code throw an exception:
decimal almostMax = Decimal.MaxValue - 1;
decimal x = almostMax + 0.1m; // This should create an exception, since x equals almostMax.
Assert.AreEqual(x, almostMax); // This does NOT fail.
It doesn't really matter in real code, but it would be nice to be safe.
This extension method should help. It reverses the operation and checks if the input arguments can be calculated correctly from the result. If that's not the case then the operation caused precision loss.
public static decimal Add(this decimal a, decimal b)
{
var result = a + b;
if (result - a != b || result - b != a)
throw new InvalidOperationException("Precision loss!");
return result;
}
Working example: https://dotnetfiddle.net/vx6UYY
If you want to use the regular operators like + etc, you have to go with Philipp Schmid's solution and implement the operators on your own decimal type.
You could make a SaveDecimal class and overload the + operator
https://msdn.microsoft.com/en-us/library/aa288467%28v=vs.71%29.aspx
public class SafeDecimal
{
private decimal DecValue;
public SafeDecimal(decimal Value)
{
DecValue = Value;
}
public decimal GetValue()
{
return DecValue;
}
public static SafeDecimal operator +(SafeDecimal A, SafeDecimal B)
{
decimal almostMax = Decimal.MaxValue - 1;
checked
{
if (almostMax <= A.GetValue() + B.GetValue())
throw new Exception("----scary error message----");
}
return new SafeDecimal(A.GetValue() + B.GetValue());
}
}

Equals and hashcode for vertices

I have a couple of vertices which I want to put into a Hashtable. Vertices which are really close to each other are considered as the same vertex. My C# vertex class looks like this:
public class Vertex3D
{
protected double _x, _y, _z;
public static readonly double EPSILON = 1e-10;
public virtual double x
{
get { return _x;}
set { _x = value; }
}
public virtual double y
{
get { return _y; }
set { _y = value; }
}
public virtual double z
{
get { return _z; }
set { _z = value; }
}
public Vertex3D(double p1, double p2, double p3)
{
this._x = p1;
this._y = p2;
this._z = p3;
}
public override bool Equals(object obj)
{
var other = obj as Vertex3D;
if (other == null)
{
return false;
}
double diffx = this.x - other.x;
double diffy = this.y - other.y;
double diffz = this.z - other.z;
bool eqx = diffx > -EPSILON && diffx < EPSILON;
bool eqy = diffy > -EPSILON && diffy < EPSILON;
bool eqz = diffz > -EPSILON && diffz < EPSILON;
return eqx && eqy && eqz;
}
public override int GetHashCode()
{
return this.x.GetHashCode() ^ this.y.GetHashCode() ^ this.z.GetHashCode();
}
public override string ToString()
{
return "Vertex:" + " " + x + " " + y + " " + z;
}
Now lets say I put the following two vertices into a dictionary (a dictionary is a hashtable which doesn't allow null keys):
Dictionary<Vertex3D, Vertex3D> vertexList = new Dictionary<Vertex3D, Vertex3D>();
Vertex3D v0 = new Vertex3D(0.000000000000000037842417475065449, -1, 0.00000000000000011646698526992202));
Vertex3D v1 = new Vertex3D(0, -1, 0));
vertexList.Add(v0, v0);
vertexList.Add(v1, v1);
The problem is that my implementation of equals and hashcode is faulty. The above two vertices are considered as equal because the distance to each other is smaller than EPSILON. BUT they don't return the same hashcode.
How do I implement equals and hashcode correctly?
Hashtables require equivalence classes, but your Equals() is not transitive. Therefore you cannot use a hashtable for this purpose. (If, for example, you allowed nearby objects to compare equal by rounding to lattice points, you would have transitivity and equivalence classes. But then there still would be arbitrarily close points, down to the precision of your representation, which fell on opposite sides of a threshold and thus in different equivalence classes)
There are other data structures, such as octtrees, which are designed to accelerate finding nearby points. I suggest you use one of those.
Generally, mutable-thing references should only be considered equivalent if they both refer to the same object. Only references to immutable things should use any other definition of equality. It would be helpful if Object included virtual functions to test for equivalence in the scenario where two references are held by separate objects, neither of which will expose its reference to anything that might mutate it. Unfortunately, even though the effectively-immutable-instance-of-mutable-type pattern is very common (nearly all immutable collections, for example, use one or more mutable-type objects such as arrays to hold their data) there's no standard pattern for equivalence testing with it.
If you want to store vertices in a dictionary using Object.Equals for equality testing, it should be an immutable type. Alternatively, you could define a custom IEqualityComparer<T> for use with the dictionary, but you should be aware that Dictionary should only be used to find perfect matches. If you want to be able to find any point that's within EPSILON of a given point, you should use a which maps rounded values to lists of precise values (values should be rounded to a power of two that's at least twice as great as epsilon). If adding or subtracting EPSILON from some or all of the coordinates in a point would cause it to be rounded differently, the point should be included in the dictionary, rounded every such possible way.

Creating a method with a decimal parameter that goes from 0 to 1

Is it posible to create a method with a decimal argument, that only accepts values from 0 to 1?
Example:
public decimal GetSamplingError(decimal percent){
decimal result = 0;
result = 100*percent;
return result;
}
is it posible to control that the parameter percent is compres between 0 and 1?
Thanks and sorry for my bad english.
no there is no way to control parameter's range, what you can do, is control it inside the function itself, and add a comment to the function
public decimal GetSamplingError(decimal percent){
if(percent > 1)
percent = 1;
else if(percent <0)
percent = 0;
return 100*percent;
}
Or raise an ArgumentOutOfRangeException in case if the parameter is not in dsired range, but it depends on how you would like to manage a worklfow of your application.
I would create my own type of Percent with range checks as others have suggested and some additional stuff. That way, Percent is its own entity in your application and everyone knows when and how to use it. A plain decimal might work as well, I prefer the typed approach however.
internal class Percent
{
private readonly decimal _value;
public decimal Value
{
get { return _value; }
}
public Percent(decimal value)
{
_value = (100 * value);
if (value < 0m || value > 1m)
{
throw new ArgumentOutOfRangeException("value");
}
}
public override string ToString()
{
return String.Format("{0}%", _value);
}
public override int GetHashCode()
{
// HashCode implementation;
}
public override bool Equals(object obj)
{
// Equals implementation;
}
}
There is no way of compile-time checking this. The best solution would be to check the argument at run-time:
public decimal GetSamplingError(decimal percent)
{
if (percent < 0m || percent > 1m)
{
throw new ArgumentException("Percent should be between 0 and 1!", "percent");
}
decimal result = 0;
result = 100*percent;
return result;
}
Other than the approach of Tigran, this will throw an Exception when an invalid argument is passed. I prefer this method over just changing the percent-value, becasue it'll actually make you notice that you passed a wrong value.
When you use Code Contracts of Microsoft, then you could add a contract that ensures that the value is in a specific range. When static checking is enabled, you'll get an error message at compile-time.
Contract.Requires(percent > 0m && percent < 1m, "Percent must be between 0 and 1");
You would have to do:
public decimal GetSamplingError(decimal percent){
if (percent < 0m || percent > 1m)
throw new ArgumentOutOfRangeException("percent", "Must be between 0 and 1.");
// rest of method
}
Of course, it is also possible to make your own struct called DecimalBetweenZeroAndOne which is immutable and holds a decimal field which is readonly and where you write a check to guarantee that the value of the field is always in the required range.
It is possible to validate the input and throw exception if value is not what you expected:
decimal getPercentage(decimal val)
{
if (val < 0 || val > 1)
throw new ArgumentException();
return val * 100;
}

Comparing approximate values in c# 4.0?

First of all, please excuse any typo, English is not my native language.
Here's my question. I'm creating a class that represents approximate values as such:
public sealed class ApproximateValue
{
public double MaxValue { get; private set; }
public double MinValue { get; private set; }
public double Uncertainty { get; private set; }
public double Value { get; private set; }
public ApproximateValue(double value, double uncertainty)
{
if (uncertainty < 0) { throw new ArgumentOutOfRangeException("uncertainty", "Value must be postivie or equal to 0."); }
this.Value = value;
this.Uncertainty = uncertainty;
this.MaxValue = this.Value + this.Uncertainty;
this.MinValue = this.Value - this.Uncertainty;
}
}
I want to use this class for uncertain measurments, like x = 8.31246 +/-0.0045 for example and perform calculations on these values.
I want to overload operators in this class. I don't know how to implement the >, >=, <= and < operators... The first thing I thought of is something like this:
public static bool? operator >(ApproximateValue a, ApproximateValue b)
{
if (a == null || b == null) { return null; }
if (a.MinValue > b.MaxValue) { return true; }
else if (a.MaxValue < b.MinValue) { return false; }
else { return null; }
}
However, in the last case, I'm not satisfied with this 'null' as the accurate result is not 'null'. It may be 'true' or it may be 'false'.
Is there any object in .Net 4 that would help implementing this feature I am not aware of, or am I doing the correct way? I was also thinking about using an object instead of a boolean that would define in what circumstances the value is superior or not to another one rather than implementing comparison operators but I feel it's a bit too complex for what I'm trying to achieve...
I'd probably do something like this. I'd implement IComparable<ApproximateValue> and then define <, >, <=, and >= according to the result of CompareTo():
public int CompareTo(ApproximateValue other)
{
// if other is null, we are greater by default in .NET, so return 1.
if (other == null)
{
return 1;
}
// this is > other
if (MinValue > other.MaxValue)
{
return 1;
}
// this is < other
if (MaxValue < other.MinValue)
{
return -1;
}
// "same"-ish
return 0;
}
public static bool operator <(ApproximateValue left, ApproximateValue right)
{
return (left == null) ? (right != null) : left.CompareTo(right) < 0;
}
public static bool operator >(ApproximateValue left, ApproximateValue right)
{
return (right == null) ? (left != null) : right.CompareTo(left) < 0;
}
public static bool operator <=(ApproximateValue left, ApproximateValue right)
{
return (left == null) || left.CompareTo(right) <= 0;
}
public static bool operator >=(ApproximateValue left, ApproximateValue right)
{
return (right == null) || right.CompareTo(left) <= 0;
}
public static bool operator ==(ApproximateValue left, ApproximateValue right)
{
return (left == null) ? (right == null) : left.CompareTo(right) == 0;
}
public static bool operator !=(ApproximateValue left, ApproximateValue right)
{
return (left == null) ? (right != null) : left.CompareTo(left) != 0;
}
This is one of the rare cases where it may make more sense to define a value type (struct), which then eliminates the null case concern. You can also modify MinValue and MaxValue to be computed properties (just implement a get method that computes the result) rather than storing them upon construction.
On a side note, comparison of approximate values is itself an approximate operation, so you need to consider the use cases for your data type; are you only intending to use comparison to determine when the ranges are non-overlapping? It really depends on the meaning of your type. Is this intended to represent a data point from a normally distributed data set, where the uncertainty is some number of standard deviations for the sampling? If so, it might make more sense for a comparison operation to return a numeric probability (which couldn't be called through the comparison operator, of course.)
It looks to me like you need to check if a.MaxValue == b.MinValue also, in your current implementation that would return null, which seems incorrect, it should either return true or false based on how you want the spec to actually work. I'm not sure of any built in .net functionality for this, so I believe you are going about it the correct way.
return a.Value - a.Uncertainty > b.Value + b.Uncertainty
I wouldn't really mess with the semantics of >: I think bool? is a dangerous return type here. That said, given the uncertainty, you could return true, if a is more likely to be > b.
It seems to me that you're trying to implement some form of Ternary Logic because you want the result of applying the operators to be either True, False or Indeterminate. The problem with doing that is that you really cannot combine the built-in boolean values with your indeterminate value. So whilst you could do some limited form of comparison of two ApproximateValues I think that it's inappropriate to use bool as the result of these comparisons because that implies that the result of the comparisons can be freely combined with other expressions that result in bool values, but the possibility of an indeterminate value undermines that. For example, it makes no sense to do the following when the result of operation on the left of the OR is indeterminate.
ApproximateValue approx1 = ...;
ApproximateValue approx2 = ...;
bool result = ...;
bool result = approx1 > approx2 || someBool;
So, in my opinion, I don't think that it's a good idea to implement the comparisons as operators at all if you want to retain the indeterminacy. The solutions offered here eliminate the indeterminacy, which is fine, but not what was originally specified.

Categories