Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

462
Visualizações
C # / LINQ Tomando la suma de decimales muestra diferentes resultados

Tengo una lista de objetos de los que intento sumar después de múltiples 3 de los campos entre sí. El problema es que el resultado final NO coincide cuando ejecuto el cálculo en los siguientes 2 casos:

1 - purchasesDeserialized.Sum(reference => reference.Price * reference.Box * reference.Qty)

2 - purchasesDeserialized.OrderBy(r => r.Box).Sum(reference => reference.Price * reference.Box * reference.Qty);

Los datos son idénticos en dos casos, la diferencia es que en el caso n. ° 1 hago el cálculo sin ordenar primero frente al caso n. ° 2, primero ordeno y luego calculo. (Esperaba que el resultado fuera el mismo, ya que la clasificación no debería cambiar ningún dato subyacente, sino simplemente reordenarlos).

No estoy seguro de si LINQ está afectando el cálculo después de OrderBy o si el problema aterriza en el lado del redondeo decimal de C#.

Código de replicación completo:

 using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApp1 { public class Purchase { public decimal Price { get; set; } public decimal Box { get; set; } public decimal Qty { get; set; } } class Program { static void Main(string[] args) { string purchases = "[{\"Box\":10.0,\"Qty\":206.000000,\"Price\":8.323300970873786407766990292},{\"Box\":10.0,\"Qty\":108.000000,\"Price\":8.333333333333333333333333333},{\"Box\":10.0,\"Qty\":46.000000,\"Price\":8.695652173913043478260869565},{\"Box\":10.0,\"Qty\":18.000000,\"Price\":24.833333333333333333333333333},{\"Box\":1.0,\"Qty\":566.000000,\"Price\":80.87985865724381625441696112},{\"Box\":1.0,\"Qty\":12.000000,\"Price\":97.46666666666666666666666667},{\"Box\":1.0,\"Qty\":72.000000,\"Price\":103.06805555555555555555555556},{\"Box\":1.0,\"Qty\":246.000000,\"Price\":81.2906504065040650406504065},{\"Box\":1.0,\"Qty\":78.000000,\"Price\":80.08333333333333333333333333},{\"Box\":10.0,\"Qty\":146.000000,\"Price\":8.030821917808219178082191782},{\"Box\":10.0,\"Qty\":178.000000,\"Price\":8.326404494382022471910112359},{\"Box\":10.0,\"Qty\":364.000000,\"Price\":8.324175824175824175824175825},{\"Box\":10.0,\"Qty\":30.000000,\"Price\":8.666666666666666666666666667},{\"Box\":10.0,\"Qty\":36.000000,\"Price\":24.5000000000000000000},{\"Box\":1.0,\"Qty\":120.000000,\"Price\":83.662500000000000000},{\"Box\":1.0,\"Qty\":332.000000,\"Price\":80.74698795180722891566265061},{\"Box\":1.0,\"Qty\":36.000000,\"Price\":78.833333333333333333333333333},{\"Box\":1.0,\"Qty\":22.000000,\"Price\":96.35909090909090909090909091},{\"Box\":1.0,\"Qty\":134.000000,\"Price\":78.149253731343283582089552239},{\"Box\":10.0,\"Qty\":26.000000,\"Price\":24.346153846153846153846153846},{\"Box\":1.0,\"Qty\":298.000000,\"Price\":97.06644295302013422818791947},{\"Box\":1.0,\"Qty\":18.000000,\"Price\":95.22777777777777777777777778},{\"Box\":10.0,\"Qty\":6.000000,\"Price\":24.166666666666666666666666667},{\"Box\":1.0,\"Qty\":82.000000,\"Price\":96.42195121951219512195121951},{\"Box\":10.0,\"Qty\":154.000000,\"Price\":8.149350649350649350649350649}]"; var purchasesDeserialized = JsonConvert.DeserializeObject<List<Purchase>>(purchases); var sumRes1 = purchasesDeserialized .Sum(reference => reference.Price * reference.Box * reference.Qty); Console.WriteLine("Sum:" + sumRes1); //returns 294648.40000000000000000000000M var sumRes2 = purchasesDeserialized .OrderBy(r => r.Box) .Sum(reference => reference.Price * reference.Box * reference.Qty); Console.WriteLine("Sum after sort:" + sumRes2); //returns 294648.39999999999999999999999M } } }

Y la salida:

 Sum:294648.40000000000000000000000 Sum after sort:294648.39999999999999999999999
over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Creo que el problema es que está aumentando el valor de la cantidad total (durante la operación Sum) al mismo tiempo que está disminuyendo la precisión máxima decimal.

En este caso, el orden de los elementos en la colección es importante porque afectará en qué punto se excede la precisión decimal. Los elementos restantes luego se agregarán, pero no precisamente, lo que al final da como resultado diferentes totales.

Para dar un ejemplo, digamos que mi tipo de datos puede contener hasta 4 lugares:

 var x = 4.998; var y = 0.002; var z = 10.00; x + y + z = 4.998 + 0.002 + 10.00 => 15.00; z + x + y = 10.00 + 4.998 + 0.002 => 14.99; //(because 10.00 + 4.998 = 14.99 and there is no precision left for remaining decimal place, so its stripped)
over 4 years ago · Santiago Trujillo Relatório

0

Considere, por ejemplo, los términos indexados desde su json 0 y 22

 decimal d00 = 10M * 206.000000M * 8.323300970873786407766990292M; decimal d22 = 10.0M * 6.000000M * 24.166666666666666666666666667M; decimal sum = d00 + d22;

Los resultados reales son (encontrados usando una calculadora de precisión completa )

 d00 = 17146.00000000000000000000000152 // 31 d22 = 1450.00000000000000000000000002 // 30 sum = 18596.00000000000000000000000154 // 31

pero perderá precisión al ver que d00 debe tener 31 dígitos en total, etc., y al estar limitado a la precisión decimal , los resultados en C# son

 d00 = 17146.000000000000000000000002 // 29 d22 = 1450.0000000000000000000000000 // 29 sum = 18596.000000000000000000000002 // 29

entonces el error en esta suma arbitraria es 0.000000000000000000000000046. Con la forma en que se realiza el redondeo, los errores se redondearán hacia arriba o hacia abajo, según el orden en que se realicen las operaciones de suma (50% de probabilidad de redondear de una forma u otra en cada paso), por lo que lo más probable es que termine con resultados diferentes de órdenes diferentes.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda