none
Valor mais próximo de outro valor C# RRS feed

  • Pergunta

  • Boa noite amigos,

    estou trabalhando no desenvolvimento de um software de cálculos matemáticos, e em uma das funções necessito saber qual o valor mais aproximado de 1.

    Por exemplo:
    Vamos considerar a lista:
    1,02
    0,9
    1,04
    1,4
    0,8

    Nesta lista, preciso comparar os valores e retornar aquele que esteja mais próximo do número 1.
    Existe algum método que execute esta função? Como poderia chegar nesse resultado? 

    Agradeço muito desde já.!

    terça-feira, 3 de setembro de 2013 23:54

Respostas

  • Edvaldo,

    Ajustei o método conforme sua necessidade já efetuando a comparação em double:

    public Double Verifica(Double resultado1, Double resultado2, Double resultado3)
            {
                var numbers = new List<Double>();
                numbers.Add(resultado1);
                numbers.Add(resultado2);
                numbers.Add(resultado3);
                Double pivot = 1;

                var listaMenores = new List<Double>();

                if (numbers.Where(n => n >= pivot).Any())
                {
                    listaMenores.Add(pivot + numbers.Where(n => n >= pivot).Min(n => n - pivot));
                }

                if (numbers.Where(n => n < pivot).Any())
                {
                    listaMenores.Add(pivot - numbers.Where(n => n < pivot).Min(n => pivot - n));
                }

                Double closestBelow = 0;

                if (listaMenores.Count > 0)
                {
                    closestBelow = (listaMenores.Min(n => (pivot - n) < 0 ? (pivot + ((pivot - n) * -1)) : pivot - (pivot - n)));
                }

                return closestBelow;
            }


    Ricardo Minoru Makiyama




    • Editado RMinoru quarta-feira, 4 de setembro de 2013 13:21
    • Marcado como Resposta Edvaldo Perreira quarta-feira, 4 de setembro de 2013 22:32
    quarta-feira, 4 de setembro de 2013 12:59
  • Amigo, Edvaldo

    Acredito que esteja certo porque anteriormente a lista estava vindo sem dados e os que você passou são maiores que 1 e eu estou vendo a aproximação sendo menor que 1 e maior que 1, mas agora ta certinho

    confere e se foi a resposta correta da um crédito ai!

    IList<decimal> numeros = new List<decimal>();
    numeros.Add(1.0677625596733884M);
    numeros.Add(1.0731513177917853M);
    numeros.Add(1.0808461357474586M);
    decimal pivot = 1M;
    
    var d = numeros.Where(x => x >= pivot);
    decimal MenorQueZero = 0;
    decimal MaiorQueZero = 0;
    IList<decimal> ListaMenorQueZero = numeros.Where(x => x <= pivot).ToList();
    IList<decimal> ListaMaiorQueZero = numeros.Where(x => x >= pivot).ToList();
    if (ListaMenorQueZero.Count() > 0)
    {
    	MenorQueZero = decimal.Parse(ListaMenorQueZero.Max().ToString());
    }
    if (ListaMaiorQueZero.Count() > 0)
    {
    	MaiorQueZero = decimal.Parse(ListaMaiorQueZero.Min().ToString());
    }
    if ((MaiorQueZero - pivot)  == (pivot - MenorQueZero))
    {
    	System.Console.WriteLine(string.Format("{0} e {1}", MenorQueZero, MaiorQueZero));
    } else if ((MaiorQueZero - pivot)  > (pivot - MenorQueZero))
    {
    	System.Console.WriteLine(MenorQueZero);
    } else {
    	System.Console.WriteLine(MaiorQueZero);
    }



    Fúlvio Cezar Canducci Dias

    quarta-feira, 4 de setembro de 2013 13:16

Todas as Respostas

  • Edvaldo,

    Segue um exemplo de como você pode fazer isso:

    var numbers = new List<Double> { 1.02, 0.9, 1.04, 0.8 };
    var pivot = 1;
    var closestBelow = Convert.ToDouble(pivot) - numbers.Where(n => n <= pivot).Min(n => pivot - n);


    Ricardo Minoru Makiyama



    quarta-feira, 4 de setembro de 2013 02:20
  • Boa Noite Ricardo,

    Tentei usar o que você me disse como um método, onde eu passo 3 valores para serem comparados, por favor veja se estou fazendo certo: O "N" precisa ser substituído por algum valor? Pois está dando erro de:

    A sequência não contém elementos

    Veja o método que fiz:

            public double Verifica(double resultado1, double resultado2, double resultado3 )
            {
                var numbers = new List<Double> { resultado1, resultado2, resultado3  };
                var pivot = 1;
                var closestBelow = Convert.ToDouble(pivot) - numbers.Where(n => n <= pivot).Min(n => pivot - n);
    
                return closestBelow;
            }

    quarta-feira, 4 de setembro de 2013 02:44
  • Edvaldo,

    Nesse seu caso, faça assim: 

    public double Verifica(double resultado1, double resultado2, double resultado3)
            {
                var numbers = new List<Double>();
                numbers.Add(resultado1);
                numbers.Add(resultado2);
                numbers.Add(resultado3);
                var pivot = 1;
                var closestBelow = Convert.ToDouble(pivot) - numbers.Where(n => n <= pivot).Min(n => pivot - n);

                return closestBelow;
            }

    Ricardo Minoru Makiyama



    quarta-feira, 4 de setembro de 2013 02:48
  • Ainda não deu certo,

    Continua com o mesmo erro, a linha que acontece o erro é:

    var closestBelow = Convert.ToDouble(pivot) - numbers.Where(n => n <= pivot).Min(n => pivot - n);

    InvalidOperationException was unhandled

    quarta-feira, 4 de setembro de 2013 03:02
  • Edvaldo,

    Testei o código exatamente como te passei e esta funcionando normal.

    Pode me passar os valores que você esta passando para o metodo?


    Ricardo Minoru Makiyama




    • Editado RMinoru quarta-feira, 4 de setembro de 2013 03:20
    quarta-feira, 4 de setembro de 2013 03:19
  • Os parâmetros são:

    resultado1 1.0677625596733884 double
    resultado2 1.0731513177917853 double
    resultado3 1.0808461357474586 double

    será pelo valor ser muito grande?

    -----------------------

    tentei colocar valores fixos sem casas decimais, mas também está dando problema

    quarta-feira, 4 de setembro de 2013 03:23
  • Edvaldo,

    Antes de passar os parâmetros faça uma conversão para Decimal e altere seu metodo para:

    public Decimal Verifica(Decimal resultado1, Decimal resultado2, Decimal resultado3)
            {
                var numbers = new List<Decimal>();
                numbers.Add(resultado1);
                numbers.Add(resultado2);
                numbers.Add(resultado3);
                Decimal pivot = 1;
                var closestBelow = pivot - numbers.Where(n => n <= pivot).Min(n => pivot - n);

                return closestBelow;
            }


    Ricardo Minoru Makiyama



    quarta-feira, 4 de setembro de 2013 03:34
  • Ricardo,

    O problema ainda persiste, pelo que percebi, o problema está no PIVOT. Ele pode ser menor que os valores passados pelos parâmetro? Porque colocando valor 2 nele, o código executa sem erro.

    quarta-feira, 4 de setembro de 2013 03:43
  • Assim:

    IList<decimal> numeros = new List<decimal>();
    numeros.Add(1.02M);
    numeros.Add(0.9M);
    numeros.Add(1.04M);
    numeros.Add(1.4M);
    numeros.Add(0.8M);
    numeros.Add(0.956M);
    decimal pivot = 1M;
    var c = numeros.Where(x => x <= pivot).Max().ToString();
    System.Console.WriteLine(c);

    O que foi feito, o primeiro Where pega os elementos menores ou igual ao pivot (eliminando os maiores que o pivot) e ai eu pego o valor máximo que será o mais próximo de 1


    Fúlvio Cezar Canducci Dias

    quarta-feira, 4 de setembro de 2013 04:32
  • Ou Assim

    Fiquei pensando e se mais valores empatarem tanto de aproximação para maior ou para menor

    IList<decimal> numeros = new List<decimal>();                
    numeros.Add(1.1M);
    numeros.Add(0.9M);
    numeros.Add(0.91M);
    decimal pivot = 1M;
    
    var MenorQueZero = decimal.Parse(numeros.Where(x => x <= pivot).Max().ToString());
    var MaiorQueZero = decimal.Parse(numeros.Where(x => x >= pivot).Min().ToString());
    if ((MaiorQueZero - pivot)  == (pivot - MenorQueZero))
    {
                        System.Console.WriteLine(string.Format("{0} e {1}", MenorQueZero, MaiorQueZero));
    } else if ((MaiorQueZero - pivot)  > (pivot - MenorQueZero))
    {
                        System.Console.WriteLine(MenorQueZero);
    } else {
                        System.Console.WriteLine(MaiorQueZero);
    }

    Bom Vamos ver no que dá!

    Qual daquela lista seria a resposta correta (1,02 0,9 1,04 1,4 0,8) ?????????


    Fúlvio Cezar Canducci Dias


    quarta-feira, 4 de setembro de 2013 04:51
  • Olá Fúlvio,

    Quando coloco os valores na função acontece o mesmo erro anterior:

    A sequência não contém elementos

    na última vez que ele faz a comparação dá esse problema, como posso resolver?

    estou usando 3 parametros do tipo decimal com 4 casas decimais.


    quarta-feira, 4 de setembro de 2013 04:58
  • Então  a lista acima foi somente um exemplo, na verdade eu estava criando, conforme instrução do Amigo Ricardo uma lista Double que recebia parâmetros que eram incluídos na lista.

    Mas toda vez que a função executa pela última vez dá problema. "A sequência não contém elementos';

    Essa, está relacionada ao PIVOT, de modo que, quando eu aumento o valor do PIVOT o erro não acontece.
    entretanto, se eu jogar os valores manualmente na list funciona!

    pelo menos o exemplo que você postou, funcionou com os valores fixos na list.

    Na lista de exemplo a resposta correta seria 0,9.

    var c = numeros.Where(x => x <= pivot).Max().ToString();

    quarta-feira, 4 de setembro de 2013 05:09
  • Edvaldo,

    Ajustei o método conforme sua necessidade já efetuando a comparação em double:

    public Double Verifica(Double resultado1, Double resultado2, Double resultado3)
            {
                var numbers = new List<Double>();
                numbers.Add(resultado1);
                numbers.Add(resultado2);
                numbers.Add(resultado3);
                Double pivot = 1;

                var listaMenores = new List<Double>();

                if (numbers.Where(n => n >= pivot).Any())
                {
                    listaMenores.Add(pivot + numbers.Where(n => n >= pivot).Min(n => n - pivot));
                }

                if (numbers.Where(n => n < pivot).Any())
                {
                    listaMenores.Add(pivot - numbers.Where(n => n < pivot).Min(n => pivot - n));
                }

                Double closestBelow = 0;

                if (listaMenores.Count > 0)
                {
                    closestBelow = (listaMenores.Min(n => (pivot - n) < 0 ? (pivot + ((pivot - n) * -1)) : pivot - (pivot - n)));
                }

                return closestBelow;
            }


    Ricardo Minoru Makiyama




    • Editado RMinoru quarta-feira, 4 de setembro de 2013 13:21
    • Marcado como Resposta Edvaldo Perreira quarta-feira, 4 de setembro de 2013 22:32
    quarta-feira, 4 de setembro de 2013 12:59
  • Amigo, Edvaldo

    Acredito que esteja certo porque anteriormente a lista estava vindo sem dados e os que você passou são maiores que 1 e eu estou vendo a aproximação sendo menor que 1 e maior que 1, mas agora ta certinho

    confere e se foi a resposta correta da um crédito ai!

    IList<decimal> numeros = new List<decimal>();
    numeros.Add(1.0677625596733884M);
    numeros.Add(1.0731513177917853M);
    numeros.Add(1.0808461357474586M);
    decimal pivot = 1M;
    
    var d = numeros.Where(x => x >= pivot);
    decimal MenorQueZero = 0;
    decimal MaiorQueZero = 0;
    IList<decimal> ListaMenorQueZero = numeros.Where(x => x <= pivot).ToList();
    IList<decimal> ListaMaiorQueZero = numeros.Where(x => x >= pivot).ToList();
    if (ListaMenorQueZero.Count() > 0)
    {
    	MenorQueZero = decimal.Parse(ListaMenorQueZero.Max().ToString());
    }
    if (ListaMaiorQueZero.Count() > 0)
    {
    	MaiorQueZero = decimal.Parse(ListaMaiorQueZero.Min().ToString());
    }
    if ((MaiorQueZero - pivot)  == (pivot - MenorQueZero))
    {
    	System.Console.WriteLine(string.Format("{0} e {1}", MenorQueZero, MaiorQueZero));
    } else if ((MaiorQueZero - pivot)  > (pivot - MenorQueZero))
    {
    	System.Console.WriteLine(MenorQueZero);
    } else {
    	System.Console.WriteLine(MaiorQueZero);
    }



    Fúlvio Cezar Canducci Dias

    quarta-feira, 4 de setembro de 2013 13:16
  • Ricardo,

    Muito Obrigado, com os ajustes que você fez o código ficou perfeito!
    fazendo as comparações, não acontece mais o erro. Já apliquei ao código.

    quarta-feira, 4 de setembro de 2013 22:35
  • Fúlvio,

    O seu código também deu certo, entretanto, utilizei o do Ricardo, pois os valores já estavam todos em Double e com o método com retorno.

    Mas marquei como resposta também, pois rodei o comando e também cheguei ao resultado menor.
    Muito Obrigado pela atenção!

    quarta-feira, 4 de setembro de 2013 22:37