0
List<decimal> list = new List<decimal>() { 23.346m, 23.56m, 4.2m, 0.90000000000000000000000000000m, 0.59333800m};

Console.WriteLine(list.OrderByDescending( a=>a)
.Max());

How can I sort this list and get the value with the maximum numbers after the .?

Expected Outcome:

Sorted like this

// 0.593338m

// 23.346m

// 23.56m

// 4.2m

// 0.9m

and the Longest Value expected is:

// 0.593338m

Dev
  • 1,780
  • 3
  • 18
  • 46
  • Can you please clarify how `0.900m` and `0.90m` should be compared? You explicitly used `decimal` to preserve trailing zeros - do you want to compare total length (including trailing zeros) or only significant digits (ignoring trailing zeros) as one can guess from your "expected" results? – Alexei Levenkov Aug 29 '23 at 17:54

2 Answers2

1

How about this :

List<decimal> list = new List<decimal>() { 23.346m, 23.56m, 4.2m, 0.90000000000000000000000000000m, 0.59333800m};
List<string> lists = list.Select(x => x.ToString("0.##############################")).ToList();
Console.WriteLine(lists.OrderByDescending( a=>a.Substring(a.IndexOf('.')).Length).Max());

First convert the list to a list of strings - the format string is required to remove trailing zeroes from the string version of decimals, as they will retain the precision used when defined. # format specifier truncates 0s to the right, 29 #s are required as that is the most precision a decimal can have.

Then order by string length of the string after the decimal point..

PaulF
  • 6,673
  • 2
  • 18
  • 29
0

You can use pure math to get the desired result which is more efficient than string conversions, but it's tricky to resolve the right side after the decimal separator and convert it to an integer.

With following methods the query to get the result is easy:

decimal result = list.MaxBy(GetValueAfterDecimalSeparator);

public static int GetValueAfterDecimalSeparator(decimal d)
{
    decimal normalized = Normalize(d); // remove trailing zeros
    int countDecimalNumbers = BitConverter.GetBytes(decimal.GetBits(normalized)[3])[2];
    decimal leftValue = System.Math.Floor(normalized);
    decimal rightValue = Math.Abs(leftValue - normalized);
    try
    {
        int multiplier = (int)Math.Pow(10, countDecimalNumbers);
        return Decimal.ToInt32(Decimal.Multiply(rightValue, multiplier));
    }
    catch(OverflowException)
    {
        return int.MaxValue;
    }
}
    
public static decimal Normalize(decimal value)
{
    return value/1.000000000000000000000000000000000m;
}

The Normalize method came from here.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939