我正在研究一个简单的数学库用于教育目的,我已经实现了一个struct代表Rational Number的数学库.显示结构核心字段的非常基本的代码是:
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;
}
...
}
Run Code Online (Sandbox Code Playgroud)
目前我正在实现一个RationalMatrix,你可能已经猜到,它将由RationalNumber类型元素组成.
我正在创建静态构建器的有用矩阵是Identity矩阵.代码如下:
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);
}
Run Code Online (Sandbox Code Playgroud)
问题是这不起作用,因为my的默认值RationalNumber不是,0/1但是0/0这是一种特殊的值(Indeterminate form).
显然,一个解决方案很简单,只需将方法更改为:
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);
}
Run Code Online (Sandbox Code Playgroud)
但这在某种程度上似乎是浪费精力,因为我基本上是将整个数组的值初始化两次.我认为以某种方式使默认值RationalNumber相等会更优雅0/1.如果RationalNumber是a class,那么这很容易做到,但是当它是a时,我想不出办法struct.我错过了一些明显的东西,或者没有办法避免 0/0作为我的默认值?
我想指出的是,我并不关心代码性能(如果这是我的瓶颈,那么我已经远远超过了我的目标).我只是想知道是否有一些构造(我不知道)允许你在一个中强加任意默认值struct.
编辑:错别字
编辑2:扩大问题范围
好吧,struct根据我有限的C#知识,似乎没有办法从我得到的输入和我自己的结论中强加任意默认值.
有人能给我一个线索,为什么结构必须这样做?是出于某种原因还是以这种方式实现,因为没有人想过指定定义默认值的选项?
如果您不必区分不确定的0/0和其他0/N值,则可以将所有0/N视为零.也就是说,所有零都是有意义的(0/2等于0/1),并且所有除以零都是相等的,因此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();
}
}
Run Code Online (Sandbox Code Playgroud)
最好为该结构提供一个默认构造函数:
public RationalNumber()
{
this.numerator = 0;
this.denominator = 1;
this.isDefinitelyCoprime = false;
}
Run Code Online (Sandbox Code Playgroud)
然而这是不允许的。您也不能拥有实例初始化程序。
答案很简单,您必须接受内部字段必须初始化为零,但这并不意味着行为必须遵循。
public struct Rational
{
private int _numerator;
private int _denominator;
public Rational(int numerator, int denominator)
{
// Check denominator is positive.
if(denominator < 0){
denominator *= -1;
numerator *= -1;
}
_numerator = numerator;
_denominator = denominator== 0? -1:
denominator;
}
public int Numerator
{
get { return _numerator; }
}
public int Denominator
{
get { return
_denominator == 0?1:
_denominator == -1?0:
_denominator; }
}
}
Run Code Online (Sandbox Code Playgroud)
(注意:我实际上非常惊讶地发现结构中不能有静态初始化器!)