Default value for Rational Number struct

c#, struct

Solution

If you do not have to distinguish between the indeterminate 0/0 and other 0/N values, then you can treat all your 0/N as zero. That is, all zeros are equal which makes sense (0/2 equals 0/1), and also all divisions by zero are equal, so 1/0 == 2/0.

public struct RationalNumber : IEquatable<RationalNumber>
{
    private readonly long numerator;
    private readonly long denominator;

    public RationalNumber(long numerator, long denominator)
    {
        this.numerator = numerator;
        this.denominator = denominator;
    }

    public bool IsZero 
    { 
       get { return numerator == 0; }
    }

    public bool IsInvalid 
    { 
       get { return denominator == 0 && numerator != 0; }
    }

    public bool Equals(RationalNumber r)
    {
       if (r.IsZero && IsZero)
         return true;
       if (r.IsInvalid && IsInvalid)
         return true;
       return denominator == r.denominator && numerator == r.numerator;
    }

    public bool Equals(object o)
    {
       if (!(o is RationalNumber))
         return false;
       return Equals((RationalNumber)o);
    }

    public int GetHashCode()
    {
       if (IsZero) 
         return 0;
       if (IsInvalid)
         return Int32.MinValue;
       return ((float)numerator/denominator).GetHashCode();
    }
}   

Problem

I'm working on a simple math library for educational purposes and I've implemented a `struct` that represents a Rational Number. Very basic code showing the core fields of the struct is: ``` public struct RationalNumber { private readonly long numerator; private readonly long denominator; private bool isDefinitelyCoprime; private static RationalNumber zero = 0; public RationalNumber(long numerator, long denominator) { this.numerator = numerator; this.denominator = denominator; this.isDefinitelyCoprime = false; } ... } ``` Currently I'm implementing a `RationalMatrix` which, as you've probably guessed, will be made up of `RationalNumber` typed elements. A useful matrix that I'm creating a static builder for is the Identity matrix. Code is as follows: ``` public static RationalMatrix GetIdentityMatrix(int dimension) { RationalNumber[,] values = new RationalNumber[dimension, dimension]; for (int i = 0; i < dimension; i++) values[i, i] = 1; return new RationalMatrix(values); } ``` The problem is that this will not work because the default value of my `RationalNumber` is not `0/1` but `0/0` which is a special kind of value (Indeterminate form). Obviously one solution is straightforward and it is to simply change the method to: ``` public static RationalMatrix GetIdentityMatrix(int dimension) { RationalNumber[,] values = new RationalNumber[dimension, dimension]; for (int i = 0; i < dimension; i++) for (int j = i+1 ; j < dimension; j++) { values[i, i] = 1; values[i, j] = RationalNumber.Zero; values[j, i] = RationalNumber.Zero; } return new RationalMatrix(values); } ``` But this somehow seems a waste of effort as I'm basically initializing the values of the whole array two times. I kind of think it would be more elegant to somehow make the default value of `RationalNumber` equal `0/1`. This would be easy to do if RationalNumber were a `class`, but I can't think of a way to do it when it's a `struct`. Am I missing something obvious or is there no way to avoid having `0/0` as my default value? I'd like to point out that I am not concerned at all about code performance (if this were to be my bottleneck then I'd be far past my goals already). I'm just curious to know if there is some construct (unknown to me) that allows you to impose arbitrary default values in a `struct`. EDIT: Typos EDIT 2: Broaden scope of question OK, it seems there is no way to impose arbitrary default values in a `struct` from the input I'm getting and from my own conclusions based on my limited C# knowledge. Can someone give me a clue as to why structs must behave this way? Is it for a reason or was it implemented this way because no one thought to specify the option to define default values?

Original source