< Summary

Class:Towel.Mathematics.Fraction<T>
Assembly:Towel
File(s):File 1: /home/runner/work/Towel/Towel/Sources/Towel/Mathematics/Fraction.cs
Covered lines:81
Uncovered lines:89
Coverable lines:170
Total lines:540
Line coverage:47.6% (81 of 170)
Covered branches:25
Total branches:48
Branch coverage:52% (25 of 48)

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_Numerator()100%1100%
File 1: set_Numerator(...)100%10%
File 1: get_Denominator()100%1100%
File 1: set_Denominator(...)0%20%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)50%275%
File 1: op_Implicit(...)100%10%
File 1: op_UnaryNegation(...)100%10%
File 1: Negate(...)100%10%
File 1: op_Addition(...)100%1100%
File 1: Add(...)100%1100%
File 1: op_Subtraction(...)100%1100%
File 1: Subtract(...)100%1100%
File 1: op_Multiply(...)100%1100%
File 1: Multiply(...)100%1100%
File 1: op_Division(...)100%10%
File 1: Divide(...)100%10%
File 1: op_Modulus(...)100%10%
File 1: Remainder(...)0%20%
File 1: Remainder(...)100%10%
File 1: ReduceInternal(...)75%473.33%
File 1: Reduce(...)100%10%
File 1: Reduce()100%10%
File 1: op_Equality(...)100%1100%
File 1: Equality(...)50%2100%
File 1: Equality(...)100%10%
File 1: Equals(...)0%20%
File 1: op_Inequality(...)100%10%
File 1: NotEqual(...)0%20%
File 1: NotEqual(...)100%10%
File 1: op_LessThan(...)100%10%
File 1: LessThan(...)100%10%
File 1: LessThan(...)100%10%
File 1: op_GreaterThan(...)100%10%
File 1: GreaterThan(...)100%10%
File 1: GreaterThan(...)100%10%
File 1: op_LessThanOrEqual(...)100%10%
File 1: LessThanOrEqual(...)100%10%
File 1: LessThanOrEqual(...)100%10%
File 1: op_GreaterThanOrEqual(...)100%10%
File 1: GreaterThanOrEqual(...)100%10%
File 1: GreaterThanOrEqual(...)100%10%
File 1: Compare(...)100%10%
File 1: Compare(...)0%40%
File 1: GetHashCode()100%10%
File 1: TryParse(...)100%2100%
File 1: TryParse(...)100%18100%
File 1: Parse(...)0%20%
File 1: ToString()100%10%
File 1: ToString(...)0%40%
File 1: ToString(...)0%20%

File(s)

/home/runner/work/Towel/Towel/Sources/Towel/Mathematics/Fraction.cs

#LineLine coverage
 1namespace Towel.Mathematics;
 2
 3/// <summary>Represents a rational value with a numerator and a denominator.</summary>
 4/// <typeparam name="T">The type of the numerator and denominator.</typeparam>
 5public struct Fraction<T>
 6{
 7  internal T _numerator;
 8  internal T _denominator;
 9
 10  #region Properties
 11
 12  /// <summary>The numerator of the fraction.</summary>
 13  public T Numerator
 14  {
 9615    get => _numerator;
 016    set => _numerator = value;
 17  }
 18
 19  /// <summary>The denominator of the fraction.</summary>
 20  public T Denominator
 21  {
 16022    get => _denominator;
 23    set
 024    {
 025      if (Equate(value, Constant<T>.Zero))
 026      {
 027        throw new ArgumentOutOfRangeException(nameof(value), value, "!(" + nameof(value) + " != 0)");
 28      }
 029      _denominator = value;
 030    }
 31  }
 32
 33  #endregion
 34
 35  #region Constructors
 36
 37  /// <summary>Constructs a new fraction [<paramref name="numerator"/> / 1].</summary>
 38  /// <param name="numerator">The numerator of the fraction.</param>
 39  public Fraction(T numerator)
 340  {
 341    _numerator = numerator;
 342    _denominator = Constant<T>.One;
 343  }
 44
 45  /// <summary>Constructs a new fraction [<paramref name="numerator"/> / <paramref name="deniminator"/>].</summary>
 46  /// <param name="numerator">The numerator of the fraction.</param>
 47  /// <param name="deniminator">The denominator of the fraction.</param>
 48  public Fraction(T numerator, T deniminator)
 20749  {
 20750    if (Equate(deniminator, Constant<T>.Zero))
 051    {
 052      throw new ArgumentOutOfRangeException(nameof(deniminator), deniminator, nameof(deniminator) + " is 0");
 53    }
 20754    ReduceInternal(numerator, deniminator, out T reducedNumerator, out T reducedDenominator);
 20755    _numerator = reducedNumerator;
 20756    _denominator = reducedDenominator;
 20757  }
 58
 59  #endregion
 60
 61  #region Cast
 62
 63  /// <summary>Implicitly converts a value into a fraction.</summary>
 64  /// <param name="value">The value to convert to a fraction.</param>
 65  public static implicit operator Fraction<T>(T value) =>
 066    new(value);
 67
 68  #endregion
 69
 70  #region Negation
 71
 72  /// <summary>Negates a value.</summary>
 73  /// <param name="a">The fraction to negate.</param>
 74  /// <returns>The result of the negation.</returns>
 075  public static Fraction<T> operator -(Fraction<T> a) => Fraction<T>.Negate(a);
 76
 77  /// <summary>Negates a value.</summary>
 78  /// <param name="a">The value to negate.</param>
 79  /// <returns>The result of the negation.</returns>
 80  public static Fraction<T> Negate(Fraction<T> a) =>
 081    new(Negation(a.Numerator), a.Denominator);
 82
 83  #endregion
 84
 85  #region Addition
 86
 87  /// <summary>Adds two values.</summary>
 88  /// <param name="a">The left operand.</param>
 89  /// <param name="b">The right operand.</param>
 90  /// <returns>The result of the addition.</returns>
 2091  public static Fraction<T> operator +(Fraction<T> a, Fraction<T> b) => Fraction<T>.Add(a, b);
 92
 93  /// <summary>Adds two values.</summary>
 94  /// <param name="a">The left operand.</param>
 95  /// <param name="b">The right operand.</param>
 96  /// <returns>The result of the addition.</returns>
 97  public static Fraction<T> Add(Fraction<T> a, Fraction<T> b)
 2098  {
 2099    T c = Multiplication(a.Numerator, b.Denominator);
 20100    T d = Multiplication(b.Numerator, a.Denominator);
 20101    T e = Addition(c, d);
 20102    T f = Multiplication(a.Denominator, b.Denominator);
 20103    return new Fraction<T>(e, f);
 20104  }
 105
 106  #endregion
 107
 108  #region Subtraction
 109
 110  /// <summary>Subtracts two values.</summary>
 111  /// <param name="a">The left operand.</param>
 112  /// <param name="b">The right operand.</param>
 113  /// <returns>The result of the subtraction.</returns>
 114  public static Fraction<T> operator -(Fraction<T> a, Fraction<T> b) =>
 12115    Fraction<T>.Subtract(a, b);
 116
 117  /// <summary>Subtracts two values.</summary>
 118  /// <param name="a">The left operand.</param>
 119  /// <param name="b">The right operand.</param>
 120  /// <returns>The result of the subtraction.</returns>
 121  public static Fraction<T> Subtract(Fraction<T> a, Fraction<T> b)
 12122  {
 12123    T c = Multiplication(a.Numerator, b.Denominator);
 12124    T d = Multiplication(b.Numerator, a.Denominator);
 12125    T e = Subtraction(c, d);
 12126    T f = Multiplication(a.Denominator, b.Denominator);
 12127    return new Fraction<T>(e, f);
 12128  }
 129
 130  #endregion
 131
 132  #region Multiplication
 133
 134  /// <summary>Multiplies two values.</summary>
 135  /// <param name="a">The left operand.</param>
 136  /// <param name="b">The right operand.</param>
 137  /// <returns>The result of the multiplication.</returns>
 138  public static Fraction<T> operator *(Fraction<T> a, Fraction<T> b) =>
 16139    Fraction<T>.Multiply(a, b);
 140
 141  /// <summary>Multiplies two values.</summary>
 142  /// <param name="a">The left operand.</param>
 143  /// <param name="b">The right operand.</param>
 144  /// <returns>The result of the multiplication.</returns>
 145  public static Fraction<T> Multiply(Fraction<T> a, Fraction<T> b) =>
 16146    new(
 16147      Multiplication(a.Numerator, b.Numerator),
 16148      Multiplication(a.Denominator, b.Denominator));
 149
 150  #endregion
 151
 152  #region Division
 153
 154  /// <summary>Divides two values.</summary>
 155  /// <param name="a">The left operand.</param>
 156  /// <param name="b">The right operand.</param>
 157  /// <returns>The result of the division.</returns>
 158  public static Fraction<T> operator /(Fraction<T> a, Fraction<T> b) =>
 0159    Fraction<T>.Divide(a, b);
 160
 161  /// <summary>Divides two values.</summary>
 162  /// <param name="a">The left operand.</param>
 163  /// <param name="b">The right operand.</param>
 164  /// <returns>The result of the division.</returns>
 165  public static Fraction<T> Divide(Fraction<T> a, Fraction<T> b) =>
 0166    new(
 0167      Multiplication(a.Numerator, b.Denominator),
 0168      Multiplication(a.Denominator, b.Numerator));
 169
 170  #endregion
 171
 172  #region Remainder
 173
 174  /// <summary>Computes the remainder of two values.</summary>
 175  /// <param name="a">The left operand.</param>
 176  /// <param name="b">The right operand.</param>
 177  /// <returns>The result of the remainder operation.</returns>
 178  public static Fraction<T> operator %(Fraction<T> a, Fraction<T> b) =>
 0179    Fraction<T>.Remainder(a, b);
 180
 181  /// <summary>Computes the remainder of two values.</summary>
 182  /// <param name="a">The left operand.</param>
 183  /// <param name="b">The right operand.</param>
 184  /// <returns>The result of the remainder operation.</returns>
 185  public static Fraction<T> Remainder(Fraction<T> a, Fraction<T> b)
 0186  {
 0187    while (a > b)
 0188    {
 0189      a -= b;
 0190    }
 0191    return a;
 0192  }
 193
 194  /// <summary>Computes the remainder of two values.</summary>
 195  /// <param name="b">The right operand.</param>
 196  /// <returns>The result of the remainder operation.</returns>
 197  public Fraction<T> Remainder(Fraction<T> b) =>
 0198    Fraction<T>.Remainder(this, b);
 199
 200  #endregion
 201
 202  #region Reduce
 203
 204  internal static void ReduceInternal(T a, T b, out T c, out T d)
 207205  {
 207206    if (Statics.Equate(a, Constant<T>.Zero))
 20207    {
 20208      c = a;
 20209      d = Constant<T>.One;
 20210      return;
 211    }
 187212    T gcf = GreatestCommonFactor(a, b);
 187213    c = Division(a, gcf);
 187214    d = Division(b, gcf);
 187215    if (IsNegative(b))
 0216    {
 0217      c = Multiplication(c, Constant<T>.NegativeOne);
 0218      d = Multiplication(d, Constant<T>.NegativeOne);
 0219    }
 207220  }
 221
 222  /// <summary>Reduces a fractional value if possible.</summary>
 223  /// <param name="a">The fractional value to reduce.</param>
 224  /// <returns>The fraction in the reduced form.</returns>
 225  public static Fraction<T> Reduce(Fraction<T> a)
 0226  {
 0227    ReduceInternal(a.Numerator, a.Denominator, out T numerator, out T denominator);
 0228    return new Fraction<T>(numerator, denominator);
 0229  }
 230
 231  /// <summary>Reduces a fractional value if possible.</summary>
 232  /// <returns>The fraction in the reduced form.</returns>
 233  public Fraction<T> Reduce() =>
 0234    Fraction<T>.Reduce(this);
 235
 236  #endregion
 237
 238  #region Equality
 239
 240  /// <summary>Checks for equality between two values.</summary>
 241  /// <param name="a">The first operand.</param>
 242  /// <param name="b">The second operand.</param>
 243  /// <returns>The result of the equality check.</returns>
 244  public static bool operator ==(Fraction<T> a, Fraction<T> b) =>
 57245    Fraction<T>.Equality(a, b);
 246
 247  /// <summary>Checks for equality between two values.</summary>
 248  /// <param name="a">The first operand.</param>
 249  /// <param name="b">The second operand.</param>
 250  /// <returns>The result of the equality check.</returns>
 251  public static bool Equality(Fraction<T> a, Fraction<T> b) =>
 57252    Equate(a._numerator, b._numerator) &&
 57253    Equate(a._denominator, b._denominator);
 254
 255  /// <summary>Checks for equality between two values.</summary>
 256  /// <param name="b">The second operand.</param>
 257  /// <returns>The result of the equality check.</returns>
 258  public bool Equality(Fraction<T> b) =>
 0259    Fraction<T>.Equality(this, b);
 260
 261  /// <summary>Checks for equality with another object.</summary>
 262  /// <param name="obj">The object to equate with this.</param>
 263  /// <returns>The result of the equate.</returns>
 264  public override bool Equals(object? obj) =>
 0265    obj is Fraction<T> fraction && Fraction<T>.Equality(this, fraction);
 266
 267  #endregion
 268
 269  #region Inequality
 270
 271  /// <summary>Checks for inequality between two values.</summary>
 272  /// <param name="a">The first operand.</param>
 273  /// <param name="b">The second operand.</param>
 274  /// <returns>The result of the inequality check.</returns>
 275  public static bool operator !=(Fraction<T> a, Fraction<T> b) =>
 0276    Fraction<T>.NotEqual(a, b);
 277
 278  /// <summary>Checks for inequality between two values.</summary>
 279  /// <param name="a">The first operand.</param>
 280  /// <param name="b">The second operand.</param>
 281  /// <returns>The result of the inequality check.</returns>
 282  public static bool NotEqual(Fraction<T> a, Fraction<T> b) =>
 0283    Inequate(a._numerator, b._numerator) ||
 0284    Inequate(a._denominator, b._denominator);
 285
 286  /// <summary>Checks for inequality between two values.</summary>
 287  /// <param name="b">The second operand.</param>
 288  /// <returns>The result of the inequality check.</returns>
 289  public bool NotEqual(Fraction<T> b) =>
 0290    Fraction<T>.NotEqual(this, b);
 291
 292  #endregion
 293
 294  #region LessThan
 295
 296  /// <summary>Determines if one value is less than another.</summary>
 297  /// <param name="a">The left operand.</param>
 298  /// <param name="b">The right operand.</param>
 299  /// <returns>The value of the less than operation.</returns>
 300  public static bool operator <(Fraction<T> a, Fraction<T> b) =>
 0301    Fraction<T>.LessThan(a, b);
 302
 303  /// <summary>Determines if one value is less than another.</summary>
 304  /// <param name="a">The left operand.</param>
 305  /// <param name="b">The right operand.</param>
 306  /// <returns>The value of the less than operation.</returns>
 307  public static bool LessThan(Fraction<T> a, Fraction<T> b)
 0308  {
 0309    T c = Multiplication(a.Numerator, b.Denominator);
 0310    T d = Multiplication(b.Numerator, a.Denominator);
 0311    return Statics.LessThan(c, d);
 0312  }
 313
 314  /// <summary>Determines if one value is less than another.</summary>
 315  /// <param name="b">The right operand.</param>
 316  /// <returns>The value of the less than operation.</returns>
 317  public bool LessThan(Fraction<T> b) =>
 0318    Fraction<T>.LessThan(this, b);
 319
 320  #endregion
 321
 322  #region GreaterThan
 323
 324  /// <summary>Determines if one value is greater than another.</summary>
 325  /// <param name="a">The left operand.</param>
 326  /// <param name="b">The right operand.</param>
 327  /// <returns>The value of the greater than operation.</returns>
 328  public static bool operator >(Fraction<T> a, Fraction<T> b) =>
 0329    Fraction<T>.GreaterThan(a, b);
 330
 331  /// <summary>Determines if one value is greater than another.</summary>
 332  /// <param name="a">The left operand.</param>
 333  /// <param name="b">The right operand.</param>
 334  /// <returns>The value of the greater than operation.</returns>
 335  public static bool GreaterThan(Fraction<T> a, Fraction<T> b)
 0336  {
 0337    T c = Multiplication(a.Numerator, b.Denominator);
 0338    T d = Multiplication(b.Numerator, a.Denominator);
 0339    return Statics.GreaterThan(c, d);
 0340  }
 341
 342  /// <summary>Determines if one value is greater than another.</summary>
 343  /// <param name="b">The right operand.</param>
 344  /// <returns>The value of the greater than operation.</returns>
 345  public bool GreaterThan(Fraction<T> b) =>
 0346    Fraction<T>.GreaterThan(this, b);
 347
 348  #endregion
 349
 350  #region LessThanOrEqual
 351
 352  /// <summary>Determines if one value is less than another.</summary>
 353  /// <param name="a">The left operand.</param>
 354  /// <param name="b">The right operand.</param>
 355  /// <returns>The value of the less than operation.</returns>
 356  public static bool operator <=(Fraction<T> a, Fraction<T> b) =>
 0357    Fraction<T>.LessThanOrEqual(a, b);
 358
 359  /// <summary>Determines if one value is less than another.</summary>
 360  /// <param name="a">The left operand.</param>
 361  /// <param name="b">The right operand.</param>
 362  /// <returns>The value of the less than operation.</returns>
 363  public static bool LessThanOrEqual(Fraction<T> a, Fraction<T> b)
 0364  {
 0365    T c = Multiplication(a.Numerator, b.Denominator);
 0366    T d = Multiplication(b.Numerator, a.Denominator);
 0367    return Statics.LessThanOrEqual(c, d);
 0368  }
 369
 370  /// <summary>Determines if one value is less than another.</summary>
 371  /// <param name="b">The right operand.</param>
 372  /// <returns>The value of the less than operation.</returns>
 373  public bool LessThanOrEqual(Fraction<T> b) =>
 0374    Fraction<T>.LessThanOrEqual(this, b);
 375
 376  #endregion
 377
 378  #region GreaterThanOrEqual
 379
 380  /// <summary>Determines if one value is greater than another.</summary>
 381  /// <param name="a">The left operand.</param>
 382  /// <param name="b">The right operand.</param>
 383  /// <returns>The value of the greater than operation.</returns>
 384  public static bool operator >=(Fraction<T> a, Fraction<T> b) =>
 0385    Fraction<T>.GreaterThanOrEqual(a, b);
 386
 387  /// <summary>Determines if one value is greater than another.</summary>
 388  /// <param name="a">The left operand.</param>
 389  /// <param name="b">The right operand.</param>
 390  /// <returns>The value of the greater than operation.</returns>
 391  public static bool GreaterThanOrEqual(Fraction<T> a, Fraction<T> b)
 0392  {
 0393    T c = Multiplication(a.Numerator, b.Denominator);
 0394    T d = Multiplication(b.Numerator, a.Denominator);
 0395    return Statics.GreaterThanOrEqual(c, d);
 0396  }
 397
 398  /// <summary>Determines if one value is greater than another.</summary>
 399  /// <param name="b">The right operand.</param>
 400  /// <returns>The value of the greater than operation.</returns>
 401  public bool GreaterThanOrEqual(Fraction<T> b) =>
 0402    Fraction<T>.GreaterThanOrEqual(this, b);
 403
 404  #endregion
 405
 406  #region Compare
 407
 408  /// <summary>Compares two values.</summary>
 409  /// <param name="b">The right operand.</param>
 410  /// <returns>The result of the comparison.</returns>
 411  public CompareResult Compare(Fraction<T> b) =>
 0412    Fraction<T>.Compare(this, b);
 413
 414  /// <summary>Compares two values.</summary>
 415  /// <param name="a">The left operand.</param>
 416  /// <param name="b">The right operand.</param>
 417  /// <returns>The result of the comparison.</returns>
 418  public static CompareResult Compare(Fraction<T> a, Fraction<T> b) =>
 0419    a < b ? Less :
 0420    a > b ? Greater :
 0421    Equal;
 422
 423  #endregion
 424
 425  #region Hash
 426
 427  /// <summary>Gets the default hash code for this instance.</summary>
 428  /// <returns>Teh computed hash code.</returns>
 0429  public override int GetHashCode() => HashCode.Combine(Hash(Numerator), Hash(Denominator));
 430
 431  #endregion
 432
 433  #region TryParse + Parse
 434
 435  /// <summary>Tries to parse a <see cref="string"/> into a value of the type <see cref="Fraction{T}"/>.</summary>
 436  /// <param name="string">The <see cref="string"/> to parse into a value ot type <see cref="Fraction{T}"/>.</param>
 437  /// <param name="tryParse">The <see cref="Statics.TryParse{T}"/> method of the numerator and denomiator types.</param>
 438  /// <returns>
 439  /// - <see cref="bool"/> Success: True if the parse was successful; False if not.<br/>
 440  /// - <see cref="Fraction{T}"/> Value: The value if the parse was successful or default if not.
 441  /// </returns>
 442  public static (bool Success, Fraction<T?> Value) TryParse(string @string, Func<string, (bool, T?)>? tryParse = null) =
 34443    TryParse<SFunc<string, (bool, T?)>>(@string, tryParse ?? Statics.TryParse<T>);
 444
 445  /// <summary>Tries to parse a <see cref="string"/> into a value of the type <see cref="Fraction{T}"/>.</summary>
 446  /// <typeparam name="TryParse">The type of TryParse method of the numerator and denomiator types.</typeparam>
 447  /// <param name="string">The <see cref="string"/> to parse into a value ot type <see cref="Fraction{T}"/>.</param>
 448  /// <param name="tryParse">The TryParse method of the numerator and denomiator types.</param>
 449  /// <returns>
 450  /// - <see cref="bool"/> Success: True if the parse was successful; False if not.<br/>
 451  /// - <see cref="Fraction{T}"/> Value: The value if the parse was successful or default if not.
 452  /// </returns>
 453  public static (bool Success, Fraction<T?> Value) TryParse<TryParse>(string @string, TryParse tryParse = default)
 454    where TryParse : struct, IFunc<string, (bool Success, T? Value)>
 34455  {
 34456    bool containsWhiteSpace = false;
 320457    foreach (char c in @string)
 109458    {
 109459      containsWhiteSpace = containsWhiteSpace || char.IsWhiteSpace(c);
 109460    }
 34461    if (!containsWhiteSpace)
 17462    {
 17463      int divideIndex = @string.IndexOf("/");
 17464      if (divideIndex >= 0)
 10465      {
 10466        string numeratorString = @string[..divideIndex];
 10467        string denominatorString = @string[(divideIndex + 1)..];
 10468        if (denominatorString is not "0")
 9469        {
 9470          var (numeratorSuccess, numerator) = tryParse.Invoke(numeratorString);
 9471          if (numeratorSuccess)
 7472          {
 7473            var (denominatorSuccess, denominator) = tryParse.Invoke(denominatorString);
 7474            if (denominatorSuccess && !Equate(denominator, Constant<T>.Zero))
 6475            {
 6476              return (true, new Fraction<T?>(numerator, denominator));
 477            }
 1478          }
 3479        }
 4480      }
 481      else
 7482      {
 7483        var (success, value) = tryParse.Invoke(@string);
 7484        if (success)
 3485        {
 3486          return (true, new Fraction<T?>(value));
 487        }
 4488      }
 8489    }
 25490    return (false, default);
 34491  }
 492
 493  /// <summary>Parses a string into a fraction.</summary>
 494  /// <param name="string">The string to parse.</param>
 495  /// <returns>The parsed value from the string.</returns>
 496  public static Fraction<T?> Parse(string @string)
 0497  {
 0498    var (success, value) = TryParse(@string);
 0499    if (success)
 0500    {
 0501      return value;
 502    }
 503    else
 0504    {
 0505      throw new ArgumentException($@"the {nameof(@string)} parameter was not in a parsable format", nameof(@string));
 506    }
 0507  }
 508
 509  #endregion
 510
 511  #region ToString
 512
 513  /// <summary>Default conversion to string for fractions.</summary>
 514  /// <returns>The value represented as a string.</returns>
 0515  public override string? ToString() => ToString(this);
 516
 517  /// <summary>Default conversion to string for fractions.</summary>
 518  /// <param name="fraction">The value to convert.</param>
 519  /// <param name="toString">The string conversion function for the numerator and denominator.</param>
 520  /// <returns>The value represented as a string.</returns>
 521  public static string? ToString(Fraction<T> fraction, Func<T, string?>? toString = null) =>
 0522    ToString<SFunc<T, string?>>(fraction, toString ?? (value => value is null ? string.Empty : value.ToString()));
 523
 524  /// <summary>Default conversion to string for fractions.</summary>
 525  /// <typeparam name="TToString">The type of the string conversion function for the numerator and denominator.</typepar
 526  /// <param name="fraction">The value to convert.</param>
 527  /// <param name="toString">The string conversion function for the numerator and denominator.</param>
 528  /// <returns>The value represented as a string.</returns>
 529  public static string? ToString<TToString>(Fraction<T> fraction, TToString toString = default)
 530    where TToString : struct, IFunc<T, string?>
 0531  {
 0532    if (Equate(fraction._denominator, Constant<T>.One))
 0533    {
 0534      return toString.Invoke(fraction._numerator);
 535    }
 0536    return toString.Invoke(fraction._numerator) + "/" + toString.Invoke(fraction._denominator);
 0537  }
 538
 539  #endregion
 540}