1

Thanks you for reaching out!

I have a list of doubles:

List<double> list = new List<double>()
{
       2.7, -3.5, 0.6, 34.83, 7.458, 0, 9.20, -20.40, 12.2
};

How can I retrieve the number that contains the most digits after the comma? (in this case 7.458)

What I tried so far was to declare a DecimalSeparator

NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";

and to try and Split (using LINQ) every number from the list

list.Split(nfi);

but I can't do that because it's a list of doubles, should I convert the list to a list of strings and then go from there? Or is it another method that I don't know about...

Thanks in advance for the response! Have a great day! :D

(Sorry if the question is too basic... I'm new to C# :c )

Stinray
  • 15
  • 6
  • 6
    *"should I convert the list to a list of strings and then go from there?"* To me, it seems to be a good way to start. Go ahead, you already have found a solution – Cid Jan 12 '22 at 13:14
  • i'm curious where you get that `.Split()` from - i've never seen that method on a `List` before. – Franz Gleichmann Jan 12 '22 at 13:20
  • Does this answer your question? [Extracting mantissa and exponent from double in c#](https://stackoverflow.com/questions/389993/extracting-mantissa-and-exponent-from-double-in-c-sharp) – Crowcoder Jan 12 '22 at 13:27
  • 5
    Be aware that "0.6" may really be stored as "0.59999999999999997779553950749686919152736663818359375" – Hans Kesting Jan 12 '22 at 13:28
  • 8
    A collection of doubles are not an ideal starting point for determining 'places after the decimal point', as the internal representation is prone to [rounding issues](https://stackoverflow.com/a/54236200) when presented in base 10. A decimal (optimised for base 10, max 28 decimal places) or string (arbitrary precision) may be a better starting type for your numbers. – StuartLC Jan 12 '22 at 13:29
  • Please keep in mind that he is new to C# and might just want to get going. I don't think there is a need to complicate answers with "weird" functions. – Grizzlly Jan 12 '22 at 13:47
  • Thanks for sharing me the information! I do think that it's important that I know this right away, now I will keep it in mind as I go on... – Stinray Jan 12 '22 at 14:07

2 Answers2

1

Here's a possible solution:

using System;
using System.Collections.Generic;
using System.Linq;
    
public class Program
{
    public static void Main()
    {
        List<double> list = new List<double>()
        {
               2.7, -3.5, 0.6, 34.83, 7.458, 0, 9.20, -20.40, 12.2, 0.000000002
        };
        
        var max = list
            .Select(n => ((decimal)n).ToString().Split('.').ElementAtOrDefault(1))
            .Where(n => n != null)
            .Select(n => new { Number = n, Length = n.Length })
            .OrderByDescending(n => n.Length)
            .First();
        
        Console.WriteLine(max); // { Number = 000000002, Length = 9 }
    }
}

I doubt that you'll need to worry about the ToString conversion and back too much - this should only become relevant at huge list sizes. If that's your concern then you could try to work with the binary representation of the number directly instead. Note that this might reduce the 'straight-forwardness' of the solution and impact maintainability in the long run if not documented properly.

Edit 1: Edited code to reflect comment and support leading zeros. Note: decimal casting necessary to prevent scientific notation up to a number of decimal places.

FunkyPeanut
  • 1,152
  • 2
  • 9
  • 28
  • 2
    This would not select something like `0.000007`. You are filtering the highest integer value rather than the longest string after the decimal point. – Axel Kemper Jan 12 '22 at 13:30
  • Thanks! Well spotted; I've adressed your comment. – FunkyPeanut Jan 12 '22 at 13:46
  • Please keep in mind that he is new to C# and might have trouble understanding all these LINQ statements. Also, your `Number` should be the number in the list with the most digits, `0.000000002`. It looks like it is the string representation of the digits. – Grizzlly Jan 12 '22 at 13:52
  • It throws me an exception: `System.InvalidOperationException: 'Sequence contains no elements'`, it highligths the `int` in `int.Parse(n)` – Stinray Jan 12 '22 at 13:53
  • @Stinray I have copy-pasted his code in dotnetfiddle and it runs. – Grizzlly Jan 12 '22 at 13:56
  • @Grizzlly Thanks for caring! I do understand, I think... With .Select() he selects every number in the list, Splits it by '.' and then selects part 1 after the Splitting (which is the part after the comma) and so on :D Thank you so much for posting! But it still doesn't work... I don't know why https://i.imgur.com/IUlWAmu.png – Stinray Jan 12 '22 at 14:05
  • @Grizzly , FunkyPeanut Thank you so much for sharing! The code works, and I understand it. The exception was thrown because the numbers are displayed with a ' , ' comma, despite of declaring them as ' . ' , I think it's a regional thing. I replaced ' . ' with ' , ' in the code and it works! Thank you! – Stinray Jan 12 '22 at 14:17
1

Here is a more simple, basic approach:

using System;
using System.Collections.Generic;
                    
public class Program
{
    public static void Main()
    {
        List<double> list = new List<double>()
        {
            2.7, -3.5, 0.6, 34.83, 7.458, 0, 9.20, -20.40, 12.2
        };
        
        int digits = 0;
        double nr = Double.NaN;
        
        for(int i = 0; i < list.Count; ++i)
        {
            if((list[i] % 1) == 0) continue;    // If the number does not have digits: 5.0, 3.0, 7, etc.
                                                // https://stackoverflow.com/questions/2751593/how-to-determine-if-a-decimal-double-is-an-integer
            
            string nrstring = list[i].ToString();
            
            string aftercomma = nrstring.Split('.')[1];
            
            if(aftercomma.Length > digits)
            {
                digits = aftercomma.Length;
                nr = list[i];
            }
        }
        
        Console.WriteLine(nr);
    }
}

This is the fiddle.

Grizzlly
  • 486
  • 3
  • 14