EYEris
Member
- Joined
- Nov 28, 2021
- Messages
- 6
- Programming Experience
- 10+
OK, I have this class that represents a "fuzzy bit", or the closed unit interval [0,1].
My intent is to eventually make a "fuzzy byte" class, but first I was trying to create just a "fuzzy pair" of "fuzzy bits", representing values the interval [0,3].
I would later create an abstract base class they would derive from that could take any number of "bits", but one step at a time...
So, the first thing to note is when I instantiate a new Fuzzy.Bit, I still have no issues. I can work with all of them without bugs and all my unit tests pass.
I wasn't having any issues with my Fuzzy.Bit.Pair instances. They were also working and passing all tests.
I overloaded my ToString() for Fuzzy.Bit.Pair and refactored some of my code (This is where I went wrong).
Now, if/when I even try to create an uninitialized Fuzzy.Bit.Pair it gets stuck in a loop causing a stack overflow.
I know it begins with my static members of Fuzzy.Bit.Pair (ie Zero, One, Two, and Three), but the overflow happens while the Pair is creating its Bits.
I assume this has to do with implicit conversions, however, it was working before, so I'm not sure what I changed that broke it.
I have been fidgeting with this code all day and I can't figure out how to resolve this issue.
Any help would be greatly appreciated.
My intent is to eventually make a "fuzzy byte" class, but first I was trying to create just a "fuzzy pair" of "fuzzy bits", representing values the interval [0,3].
I would later create an abstract base class they would derive from that could take any number of "bits", but one step at a time...
So, the first thing to note is when I instantiate a new Fuzzy.Bit, I still have no issues. I can work with all of them without bugs and all my unit tests pass.
I wasn't having any issues with my Fuzzy.Bit.Pair instances. They were also working and passing all tests.
I overloaded my ToString() for Fuzzy.Bit.Pair and refactored some of my code (This is where I went wrong).
Now, if/when I even try to create an uninitialized Fuzzy.Bit.Pair it gets stuck in a loop causing a stack overflow.
I know it begins with my static members of Fuzzy.Bit.Pair (ie Zero, One, Two, and Three), but the overflow happens while the Pair is creating its Bits.
I assume this has to do with implicit conversions, however, it was working before, so I'm not sure what I changed that broke it.
I have been fidgeting with this code all day and I can't figure out how to resolve this issue.
Any help would be greatly appreciated.
Fuzzy.Bit.cs:
using System;
public partial class Fuzzy {
const int BASE = 2;
static int GetPower(int e) =>
(int)Math.Pow(BASE, e);
[Serializable]
public class Bit :
IComparable, IComparable<Bit>, IComparable<decimal>, IComparable<bool>,
IEquatable<Bit>, IEquatable<decimal>, IEquatable<bool>,
IFormattable
{
private const decimal
TWO = decimal.One + decimal.One,
HALF = decimal.One / TWO;
public static readonly Bit
OFF = new Bit(decimal.Zero),
ON = new Bit(decimal.One);
private decimal _value = 0M;
public decimal CarryAmount = 0, BorrowAmount = 0;
public decimal Clamp(decimal value) {
while(value < 0) { value += 1; BorrowAmount += 1; }
while(value > 1) { value -= 1; CarryAmount += 1; }
return value;
}
public decimal D_Value {
get => _value;
set => _value = Clamp(value);
}
public decimal R_Value => Math.Round(D_Value, 2);
public bool B_Value => D_Value >= HALF;
public int I_Value => B_Value ? 1 : 0;
public decimal TrueValue => D_Value + CarryAmount - BorrowAmount;
public Bit(decimal value) => D_Value = value;
public Bit(bool value) => D_Value = value ? decimal.One : decimal.Zero;
public int CompareTo(bool b) => B_Value.CompareTo(b);
public int CompareTo(decimal d) => TrueValue.CompareTo(d);
public int CompareTo(Bit B) => TrueValue.CompareTo(B.TrueValue);
public int CompareTo( object o) => TrueValue.CompareTo(o);
public bool Equals(bool b) => B_Value.Equals(b);
public bool Equals(decimal d) => TrueValue.Equals(d);
public bool Equals(Bit B) => TrueValue.Equals(B.TrueValue);
public override bool Equals(object o) =>
o as Bit != null && TrueValue == (o as Bit).TrueValue;
public override int GetHashCode() => TrueValue.GetHashCode();
private string GenerateString(string trueValue, string roundValue, string carryAmt, string borrowAmt) =>
trueValue +
(TrueValue != D_Value ? " (" + roundValue +
( CarryAmount > 0 ? $", +{carryAmt}" : "") +
(BorrowAmount > 0 ? $", - {borrowAmt}" : "") +
")" : "");
public override string ToString() =>
GenerateString(
TrueValue.ToString(),
R_Value.ToString(),
CarryAmount.ToString(),
BorrowAmount.ToString()
);
public string ToString(string format) =>
GenerateString(
TrueValue.ToString(format),
R_Value.ToString(format),
CarryAmount.ToString(format),
BorrowAmount.ToString(format)
);
public string ToString(IFormatProvider formatProvider) =>
GenerateString(
TrueValue.ToString(formatProvider),
R_Value.ToString(formatProvider),
CarryAmount.ToString(formatProvider),
BorrowAmount.ToString(formatProvider)
);
public string ToString(string format, IFormatProvider formatProvider) =>
GenerateString(
TrueValue.ToString(format, formatProvider),
R_Value.ToString(format, formatProvider),
CarryAmount.ToString(format, formatProvider),
BorrowAmount.ToString(format, formatProvider)
);
public static implicit operator Bit( bool b) => new Bit(b);
public static implicit operator Bit(decimal d) => new Bit(d);
public static implicit operator bool(Bit B) => B.B_Value;
public static implicit operator decimal(Bit B) => B.TrueValue;
//public static explicit operator Bit(int i) => new Bit(i);
//public static explicit operator int(Bit B) => B.I_Value + (int)(B.CarryAmout - B.BorrowAmount);
public static bool operator true(Bit B) => B.B_Value;
public static bool operator false(Bit B) => !B.B_Value;
public static bool operator ==(Bit B, decimal d) => B.TrueValue == d;
public static bool operator !=(Bit B, decimal d) => B.TrueValue != d;
public static bool operator <(Bit B, decimal d) => B.TrueValue < d;
public static bool operator <=(Bit B, decimal d) => B.TrueValue <= d;
public static bool operator >(Bit B, decimal d) => B.TrueValue > d;
public static bool operator >=(Bit B, decimal d) => B.TrueValue >= d;
public static Bit operator +(Bit A, Bit B) => A.TrueValue + B.TrueValue;
public static Bit operator -(Bit A, Bit B) => A.TrueValue - B.TrueValue;
[Serializable]
public class Pair :
IComparable,
IComparable<Pair>, IComparable<Bit[]>, IComparable<decimal>, IComparable<int>,
IEquatable <Pair>, IEquatable <Bit[]>, IEquatable <decimal>, IEquatable <int>,
IFormattable
{
const int size = 2, limit = BASE * size - 1;
public static readonly Pair
Zero = new Pair(new Bit[2] { 0, 0 }),
One = new Pair(new Bit[2] { 0, 1 }),
Two = new Pair(new Bit[2] { 1, 0 }),
Three = new Pair(new Bit[2] { 1, 1 });
public Bit[] BitArray = new Bit[2] { 0, 0 };
public Bit this[int i] {
get => BitArray[i];
set => BitArray[i] = value;
}
public decimal D_Value =>
BitArray[0].D_Value * GetPower(0) +
BitArray[1].D_Value * GetPower(1);
public decimal R_Value =>
Math.Round(D_Value, 2);
public int I_Value =>
BitArray[0].I_Value * GetPower(0) +
BitArray[1].I_Value * GetPower(1);
public decimal TrueValue =>
D_Value + CarryAmount - BorrowAmount;
public Pair() =>
BitArray = Zero;
public Pair(Bit[] bitArray) =>
BitArray = Clamp(bitArray);
public Pair(int i) {
while(i > 3) { i--; CarryAmount++; }
while(i < 0) { i++; BorrowAmount++; }
switch(i) {
case 3: BitArray = Three; break;
case 2: BitArray = Two; break;
case 1: BitArray = One; break;
default: BitArray = Zero; break;
};
}
public int CompareTo( int i) => I_Value.CompareTo(i);
public int CompareTo(decimal d) => TrueValue.CompareTo(d);
public int CompareTo( Bit[] B) => CompareTo(new Pair(B).TrueValue);
public int CompareTo( Pair P) => CompareTo(P.TrueValue);
public int CompareTo( object o) => TrueValue.CompareTo(o);
public bool Equals( int i) => I_Value.Equals(i);
public bool Equals(decimal d) => TrueValue.Equals(d);
public bool Equals( Pair P) => TrueValue.Equals(P.TrueValue);
public bool Equals( Bit[] B) => BitArray.Equals(B);
public override bool Equals(object o) =>
o as Pair != null && TrueValue == (o as Pair).TrueValue;
public override int GetHashCode() => TrueValue.GetHashCode();
private string GenerateString(string trueValue, string roundValue, string carryAmt, string borrowAmt) =>
trueValue +
(TrueValue != D_Value ? " (" + roundValue +
( CarryAmount > 0 ? $", +{carryAmt}" : "") +
(BorrowAmount > 0 ? $", -{borrowAmt}" : "") +
")" : "");
public override string ToString() =>
GenerateString(
TrueValue.ToString(),
R_Value.ToString(),
CarryAmount.ToString(),
BorrowAmount.ToString()
);
public string ToString(string format) =>
GenerateString(
TrueValue.ToString(format),
R_Value.ToString(format),
CarryAmount.ToString(format),
BorrowAmount.ToString(format)
);
public string ToString(IFormatProvider formatProvider) =>
GenerateString(
TrueValue.ToString(formatProvider),
R_Value.ToString(formatProvider),
CarryAmount.ToString(formatProvider),
BorrowAmount.ToString(formatProvider)
);
public string ToString(string format, IFormatProvider formatProvider) =>
GenerateString(
TrueValue.ToString(format, formatProvider),
R_Value.ToString(format, formatProvider),
CarryAmount.ToString(format, formatProvider),
BorrowAmount.ToString(format, formatProvider)
);
//public static implicit operator Pair(decimal d) => new Pair(d);
public static implicit operator Pair( int i) => new Pair(i);
public static implicit operator Pair( Bit[] B) => new Pair(B);
//public static implicit operator decimal(Pair B) => B.TrueValue;
public static implicit operator Bit[](Pair B) => B.BitArray;
public static implicit operator int(Pair B) => B.I_Value;
public static bool operator ==(Pair B, int i) => B.I_Value == i;
public static bool operator ==(Pair B, decimal d) => B.D_Value == d;
public static bool operator !=(Pair B, int i) => B.I_Value != i;
public static bool operator !=(Pair B, decimal d) => B.D_Value != d;
public static bool operator <(Pair B, int i) => B.I_Value < i;
public static bool operator <(Pair B, decimal d) => B.D_Value < d;
public static bool operator <=(Pair B, int i) => B.I_Value <= i;
public static bool operator <=(Pair B, decimal d) => B.D_Value <= d;
public static bool operator >(Pair B, int i) => B.I_Value > i;
public static bool operator >(Pair B, decimal d) => B.D_Value > d;
public static bool operator >=(Pair B, int i) => B.I_Value >= i;
public static bool operator >=(Pair B, decimal d) => B.D_Value >= d;
public decimal CarryAmount = 0, BorrowAmount = 0;
static Pair Clamp(Pair P) {
while(P.BitArray[0].BorrowAmount > 0) {
P.BitArray[1] -= 1;
P.BitArray[0].BorrowAmount -= 1;
}
while(P.BitArray[0].CarryAmount > 0) {
P.BitArray[1] += 1;
P.BitArray[0].CarryAmount -= 1;
}
while(P.BitArray[1].BorrowAmount > 0) {
P.BorrowAmount += 1;
P.BitArray[1].BorrowAmount -= 1;
}
while(P.BitArray[1].CarryAmount > 0) {
P.CarryAmount += 1;
P.BitArray[1].CarryAmount -= 1;
}
return P;
}
public static Pair operator +(Pair A, Pair B) =>
Clamp(new Bit[2]{ A[0] + B[0], A[1] + B[1] });
public static Pair operator -(Pair A, Pair B) =>
Clamp(new Bit[2]{ A[0] - B[0], A[1] - B[1] });
}
}
}
}
Last edited: