/// <summary> /// Compares two specified FixedPointDecimal values. /// </summary> /// <param name="d1">The first <see cref="FixedPointDecimal"/> to compare.</param> /// <param name="d2">The second <see cref="FixedPointDecimal"/> to compare.</param> /// <returns>A signed integer that indicates the relative values of <paramref name="d1"/> and <paramref name="d2"/>.</returns> public static int Compare(FixedPointDecimal d1, FixedPointDecimal d2) { // Test for null values. if ((d1._data & 0x80000000) == 0 && (d2._data & 0x80000000) == 0) { // Both values are null; return(0); } if ((d1._data & 0x80000000) == 0) { // d1 is null. return(-1); } if ((d2._data & 0x80000000) == 0) { // d2 is null. return(1); } // Both values are non null. Extract significands to signed int (and apply sign bit). int s1 = (int)(d1._data & 0x3FFFFFFFu | ((d1._data & 0x40000000) << 1)); int s2 = (int)(d2._data & 0x3FFFFFFFu | ((d2._data & 0x40000000) << 1)); // Compare signed significands. if (s1 > s2) { return(1); } else if (s1 < s2) { return(-1); } return(0); }
private static bool InternalTryParse(string s, out FixedPointDecimal result, bool truncateRange) { // Clean up string. Do quick null/empty test. if(null != s) { s = s.Trim(); } if(String.IsNullOrEmpty(s)) { result = FixedPointDecimal.Null; return false; } // Split string on optional decimal point. string[] parts = s.Split('.'); if(parts.Length > 2) { result = FixedPointDecimal.Null; return false; } // Test for negative sign. bool isNegative; if('-' == parts[0][0]) { isNegative = true; parts[0] = parts[0].Substring(1); if(string.IsNullOrEmpty(parts[0])) { result = FixedPointDecimal.Null; return false; } } else { isNegative = false; } // Check fractional part is no longer than 6 digits. if(parts.Length == 2 && parts[1].Length > 6) { if(truncateRange) { parts[1] = parts[1].Substring(0, 6); } else { result = FixedPointDecimal.Null; return false; } } // Join integer and fractional parts; paddign fractional part to 6 digits if necessary. // Parse resulting significand string as integer. string significandStr = parts[0] + (parts.Length == 2 ? parts[1].PadRight(6, '0') : "000000"); uint significand; if(!uint.TryParse(significandStr, out significand)) { result = FixedPointDecimal.Null; return false; } // Test significand is within range of FixedPointDecimal. if(significand > 1073741823u) { if(truncateRange) { significand = 1073741823u; } else { result = FixedPointDecimal.Null; return false; } } result = new FixedPointDecimal(significand, isNegative); return true; }
/// <summary> /// Converts the string representation of a number to its FixedPointDecimal equivalent. /// A return value indicates whether the conversion succeeded or failed. /// Values outside the range of a FixedPointDecimal are truncated to the min or max values /// for FixedPointDecimal as appropriate. Input values with more than four decimal places /// have their precision truncated to to four decimal places. /// </summary> /// <param name="s">The value to parse.</param> /// <param name="result">Upon success contains the <see cref="FixedPointDecimal"/> equivalent of the value of <paramref name="s"/>.</param> /// <returns><c>true</c> if <paramref name="s"/> could be parsed into a <see cref="FixedPointDecimal"/> instance.</returns> public static bool TryParseTruncate(string s, out FixedPointDecimal result) { return InternalTryParse(s, out result, true); }
/// <summary> /// Determines whether the specified FixedPointDecimal is equal to the current FixedPointDecimal. /// </summary> /// <param name="d1">The first <see cref="FixedPointDecimal"/> to compare.</param> /// <param name="d2">The second <see cref="FixedPointDecimal"/> to compare.</param> /// <returns><c>true</c> if the objects are equal, <c>false</c> otherwise.</returns> public static bool Equals(FixedPointDecimal d1, FixedPointDecimal d2) { // We can calculate value equality by testing bitwise equality. This is possible because we // are using a fixed point representation *and* we convert -0 to +0 (the only other possible ambiguity). return d1._data == d2._data; }
/// <summary> /// Compares two specified FixedPointDecimal values. /// </summary> /// <param name="d1">The first <see cref="FixedPointDecimal"/> to compare.</param> /// <param name="d2">The second <see cref="FixedPointDecimal"/> to compare.</param> /// <returns>A signed integer that indicates the relative values of <paramref name="d1"/> and <paramref name="d2"/>.</returns> public static int Compare(FixedPointDecimal d1, FixedPointDecimal d2) { // Test for null values. if((d1._data & 0x80000000) == 0 && (d2._data & 0x80000000) == 0) { // Both values are null; return 0; } if((d1._data & 0x80000000) == 0) { // d1 is null. return -1; } if((d2._data & 0x80000000) == 0) { // d2 is null. return 1; } // Both values are non null. Extract significands to signed int (and apply sign bit). int s1 = (int)(d1._data & 0x3FFFFFFFu | ((d1._data & 0x40000000) << 1)); int s2 = (int)(d2._data & 0x3FFFFFFFu | ((d2._data & 0x40000000) << 1)); // Compare signed significands. if(s1 > s2) { return 1; } else if(s1 < s2) { return -1; } return 0; }
/// <summary> /// Determines whether the specified FixedPointDecimal is equal to the current FixedPointDecimal. /// </summary> /// <param name="d1">The first <see cref="FixedPointDecimal"/> to compare.</param> /// <param name="d2">The second <see cref="FixedPointDecimal"/> to compare.</param> /// <returns><c>true</c> if the objects are equal, <c>false</c> otherwise.</returns> public static bool Equals(FixedPointDecimal d1, FixedPointDecimal d2) { // We can calculate value equality by testing bitwise equality. This is possible because we // are using a fixed point representation *and* we convert -0 to +0 (the only other possible ambiguity). return(d1._data == d2._data); }
private static bool InternalTryParse(string s, out FixedPointDecimal result, bool truncateRange) { // Clean up string. Do quick null/empty test. if (null != s) { s = s.Trim(); } if (String.IsNullOrEmpty(s)) { result = FixedPointDecimal.Null; return(false); } // Split string on optional decimal point. string[] parts = s.Split('.'); if (parts.Length > 2) { result = FixedPointDecimal.Null; return(false); } // Test for negative sign. bool isNegative; if ('-' == parts[0][0]) { isNegative = true; parts[0] = parts[0].Substring(1); if (string.IsNullOrEmpty(parts[0])) { result = FixedPointDecimal.Null; return(false); } } else { isNegative = false; } // Check fractional part is no longer than 6 digits. if (parts.Length == 2 && parts[1].Length > 6) { if (truncateRange) { parts[1] = parts[1].Substring(0, 6); } else { result = FixedPointDecimal.Null; return(false); } } // Join integer and fractional parts; padding fractional part to 6 digits if necessary. // Parse resulting significand string as integer. string significandStr = parts[0] + (parts.Length == 2 ? parts[1].PadRight(6, '0') : "000000"); uint significand; if (!uint.TryParse(significandStr, out significand)) { result = FixedPointDecimal.Null; return(false); } // Test significand is within range of FixedPointDecimal. if (significand > 1073741823u) { if (truncateRange) { significand = 1073741823u; } else { result = FixedPointDecimal.Null; return(false); } } result = new FixedPointDecimal(significand, isNegative); return(true); }
/// <summary> /// Converts the string representation of a number to its FixedPointDecimal equivalent. /// A return value indicates whether the conversion succeeded or failed. /// Values outside the range of a FixedPointDecimal are truncated to the min or max values /// for FixedPointDecimal as appropriate. Input values with more than four decimal places /// have their precision truncated to four decimal places. /// </summary> /// <param name="s">The value to parse.</param> /// <param name="result">Upon success contains the <see cref="FixedPointDecimal"/> equivalent of the value of <paramref name="s"/>.</param> /// <returns><c>true</c> if <paramref name="s"/> could be parsed into a <see cref="FixedPointDecimal"/> instance.</returns> public static bool TryParseTruncate(string s, out FixedPointDecimal result) { return(InternalTryParse(s, out result, true)); }