Skip to content

Commit a3ade3c

Browse files
committed
Added constructors and constructor tests
Added parse tests
1 parent 10f8861 commit a3ade3c

File tree

3 files changed

+304
-51
lines changed

3 files changed

+304
-51
lines changed

FInt/FInt.cs

Lines changed: 143 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,23 @@ public FInt Decimal
5252
}
5353

5454
/// <summary>
55-
/// Gets the sign of the number.
55+
/// Returns an integer that indicates the sign of the number.
5656
/// </summary>
57-
public FInt Sign
57+
public int Sign
5858
{
5959
get
6060
{
61-
if (_value >= 0)
61+
if(_value == 0)
62+
{
63+
return 0;
64+
}
65+
else if (_value > 0)
6266
{
63-
return 1.FI();
67+
return 1;
6468
}
6569
else
6670
{
67-
return (-1).FI();
71+
return -1;
6872
}
6973
}
7074
}
@@ -110,18 +114,23 @@ public FInt(long value)
110114
}
111115

112116
/// <summary>
113-
/// Initializes a new instance of <see cref="FInt"/> from two <see cref="int"/> values.
117+
/// Initializes a new instance of <see cref="FInt"/> from two parts: the integer and the decimal.
114118
/// </summary>
115-
/// <param name="integerValue">The integer portion of the number.</param>
116-
/// <param name="decimalValue">The decimal portion of the number.</param>
117-
/// <param name="numDecimalDigits">The number of digits in <paramref name="decimalValue"/>.</param>
119+
/// <param name="integralValue">The integer portion of the number. Can't be negative.</param>
120+
/// <param name="decimalValue">The decimal portion of the number. Can't be negative.</param>
121+
/// <param name="numDecimalDigits">The number of digits in <paramref name="decimalValue"/>. Must be between 1 and <see cref="PRECISION"/>.</param>
118122
/// <exception cref="ArgumentException"></exception>
119123
/// <exception cref="ArgumentOutOfRangeException"></exception>
120-
public FInt(int integerValue, int decimalValue, int numDecimalDigits)
124+
public FInt(int integralValue, int decimalValue, int numDecimalDigits)
121125
{
122-
if(decimalValue < 0)
126+
if (integralValue < 0)
127+
{
128+
throw new ArgumentOutOfRangeException($"Integral value cannot be negative.", nameof(integralValue));
129+
}
130+
131+
if (decimalValue < 0)
123132
{
124-
throw new ArgumentException($"Decimal value can't be negative.", nameof(decimalValue));
133+
throw new ArgumentOutOfRangeException($"Decimal value can't be negative.", nameof(decimalValue));
125134
}
126135

127136
//get the scale multiplier based on input
@@ -145,17 +154,67 @@ public FInt(int integerValue, int decimalValue, int numDecimalDigits)
145154
}
146155

147156
//assign the scaled integer value
148-
_value = integerValue * _SCALE;
157+
_value = integralValue * _SCALE;
149158

150-
//if the integer portion is negative
151-
if(integerValue < 0)
159+
//add the decimal
160+
_value += scaledDecimal;
161+
}
162+
163+
/// <summary>
164+
/// Initializes a new instance of <see cref="FInt"/> from two parts: the integer and the decimal.
165+
/// </summary>
166+
/// <param name="integralValue">The integer portion of the number. Can't be negative.</param>
167+
/// <param name="decimalValue">The decimal portion of the number. Can't be negative.</param>
168+
/// <param name="numDecimalDigits">The number of digits in <paramref name="decimalValue"/>. Must be between 1 and <see cref="PRECISION"/>.</param>
169+
/// <exception cref="ArgumentException"></exception>
170+
/// <exception cref="ArgumentOutOfRangeException"></exception>
171+
/// <exception cref="OverflowException"></exception>
172+
public FInt(long integralValue, int decimalValue, int numDecimalDigits)
173+
{
174+
if(integralValue < 0)
152175
{
153-
//subtract the decimal portion
154-
_value -= scaledDecimal;
155-
return;
176+
throw new ArgumentOutOfRangeException($"Integral value cannot be negative.", nameof(integralValue));
177+
}
178+
179+
if (decimalValue < 0)
180+
{
181+
throw new ArgumentOutOfRangeException($"Decimal value cannot be negative.", nameof(decimalValue));
182+
}
183+
184+
if (integralValue > long.MaxValue / _SCALE)
185+
{
186+
throw new OverflowException("Overflow caused by scaling integral value.");
187+
}
188+
189+
//get the scale multiplier based on input
190+
int decimalScale = numDecimalDigits switch
191+
{
192+
1 => 100_000,
193+
2 => 10_000,
194+
3 => 1_000,
195+
4 => 100,
196+
5 => 10,
197+
6 => 1,
198+
_ => throw new ArgumentOutOfRangeException(nameof(numDecimalDigits), $"Decimal digits must be between 1 and {PRECISION}.")
199+
};
200+
201+
//scale the decimal up to the correct value
202+
long scaledDecimal = decimalValue * decimalScale;
203+
204+
if (scaledDecimal >= _SCALE)
205+
{
206+
throw new ArgumentException($"Scaled decimal value '{scaledDecimal}' cannot exceed '{_SCALE}'. Check {nameof(decimalValue)} and {nameof(numDecimalDigits)}.");
207+
}
208+
209+
//assign the scaled integer value
210+
_value = integralValue * _SCALE;
211+
212+
if (long.MaxValue - _value < scaledDecimal)
213+
{
214+
throw new OverflowException($"Max value is '{MaxValue}'.");
156215
}
157216

158-
//integer is positive so add the decimal
217+
//add the decimal
159218
_value += scaledDecimal;
160219
}
161220

@@ -489,7 +548,64 @@ public static implicit operator FInt(long value)
489548
/// <returns></returns>
490549
public static FInt Parse(string s)
491550
{
492-
return new FInt(long.Parse(s));
551+
int decimalPointIndex = s.IndexOf('.');
552+
553+
if(decimalPointIndex == -1)
554+
{
555+
return long.Parse(s);
556+
}
557+
558+
string integralString = s.Substring(0, decimalPointIndex);
559+
560+
//don't take more digits that we can handle
561+
int decimalStringLength = int.Min(s.Length - (decimalPointIndex + 1), PRECISION);
562+
string decimalString = s.Substring(decimalPointIndex + 1, decimalStringLength);
563+
564+
long integralValue = 0;
565+
int decimalValue = 0;
566+
567+
int sign = 1;
568+
569+
if (integralString.Length > 0)
570+
{
571+
if (integralString == "-")
572+
{
573+
sign = -1;
574+
}
575+
else
576+
{
577+
if (integralString[0] == '-')
578+
{
579+
sign = -1;
580+
581+
//remove the negative sign
582+
integralString = integralString.Substring(1);
583+
}
584+
585+
integralValue = long.Parse(integralString);
586+
}
587+
}
588+
589+
if (decimalString.Length > 0)
590+
{
591+
if (decimalString[0] == '-')
592+
{
593+
throw new FormatException($"The input string '{s}' was not in a correct format.");
594+
}
595+
596+
decimalValue = int.Parse(decimalString);
597+
}
598+
599+
int numDecimalDigits = int.Max(1, decimalString.Length);
600+
601+
FInt result = new FInt(integralValue, decimalValue, numDecimalDigits);
602+
603+
if (sign < 0)
604+
{
605+
result = -result;
606+
}
607+
608+
return result;
493609
}
494610

495611
/// <summary>
@@ -778,8 +894,13 @@ private static int _cosLookUp(int deg)
778894

779895
public static class FIntQoLExtensions
780896
{
781-
public static FInt FI(this int i)
897+
public static FInt FI(this int value)
782898
{
783-
return new FInt(i);
899+
return value;
784900
}
901+
902+
public static FInt FI(this long value)
903+
{
904+
return value;
905+
}
785906
}

0 commit comments

Comments
 (0)