A resposta de animal_magic está correta em que você deve adicionar os números do menor para o maior, no entanto, quero dar um exemplo para mostrar o porquê.
Suponha que estamos trabalhando em um formato de ponto flutuante que nos fornece três dígitos impressionantes de precisão. Agora queremos adicionar dez números:
[1000, 1, 1, 1, 1, 1, 1, 1, 1, 1]
É claro que a resposta exata é 1009, mas não podemos obtê-la em nosso formato de 3 dígitos. Arredondando para 3 dígitos, a resposta mais precisa que obtemos é 1010. Se adicionarmos o menor ao maior, em cada loop, obtemos:
Loop Index s
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 1009 -> 1010
Portanto, obtemos a resposta mais precisa possível para o nosso formato. Agora vamos supor que adicionamos do maior para o menor.
Loop Index s
1 1000
2 1001 -> 1000
3 1001 -> 1000
4 1001 -> 1000
5 1001 -> 1000
6 1001 -> 1000
7 1001 -> 1000
8 1001 -> 1000
9 1001 -> 1000
10 1001 -> 1000
Como os números de ponto flutuante são arredondados após cada operação, todas as adições são arredondadas, aumentando nosso erro de 1 para 9 do exato. Agora imagine se o seu conjunto de números a adicionar tivesse 1000 e, em seguida, cem 1 ou um milhão. Observe que, para ser realmente preciso, você deseja somar os dois números menores e, em seguida, recorrer o resultado ao seu conjunto de números.
As respostas anteriores já discutem o assunto em geral e dão bons conselhos, mas há uma peculiaridade adicional que eu gostaria de mencionar. Na maioria das arquiteturas modernas, o
for
loop que você descreveu seria executado de qualquer maneira na precisão estendida de 80 bits , o que garante precisão adicional, pois todas as variáveis temporárias serão colocadas nos registros. Então você já tem alguma forma de proteção contra erros numéricos. No entanto, em loops mais complicados, os valores intermediários serão armazenados na memória entre as operações e, portanto, truncados para 64 bits. eu acho quebasta obter menor precisão no seu somatório (!!). Portanto, tenha muito cuidado se quiser imprimir o código-debug enquanto verifica a precisão.
Para os interessados, este artigo descreve um problema em uma rotina numérica amplamente usada (fatoração QR que revela a classificação de Lapack) cuja depuração e análise foram muito complicadas justamente por causa desse problema.
fonte
Das 2 opções, adicionar de menor a maior produzirá menos erro numérico do que adicionar de maior a menor.
No entanto, há mais de 20 anos, na minha aula de "Métodos Numéricos", o instrutor declarou isso e me ocorreu que isso ainda estava introduzindo mais erros do que o necessário, devido à diferença relativa de valor entre o acumulador e os valores que estavam sendo adicionados.
Logicamente, uma solução preferível é adicionar os 2 menores números da lista e, em seguida, reinserir o valor somado na lista classificada.
Para demonstrá-lo, elaborei um algoritmo que poderia fazer isso de forma eficiente (no espaço e no tempo) usando o espaço liberado quando os elementos foram removidos da matriz primária para criar uma matriz secundária dos valores somados que eram inerentemente ordenados desde as adições eram das somas de valores que estavam sempre aumentando. Em cada iteração, as "dicas" de ambas as matrizes são verificadas para encontrar os 2 menores valores.
fonte
Como você não restringiu o tipo de dados a ser usado, para obter um resultado perfeitamente preciso, basta usar números arbitrários de comprimento ... nesse caso, o pedido não será importante. Será muito mais lento, mas obter a perfeição leva tempo.
fonte
Use a adição da árvore binária, ou seja, escolha a média da distribuição (número mais próximo) como a raiz da árvore binária e crie uma árvore binária classificada adicionando valores menores à esquerda do gráfico e valores maiores à direita e assim por diante . Adicione todos os nós filhos de um único pai recursivamente em uma abordagem de baixo para cima. Isso será eficiente, pois o erro médio aumenta com o número de somas e, em uma abordagem de árvore binária, o número de somas está na ordem do log n na base 2. Portanto, o erro médio seria menor.
fonte
O que Hristo Iliev disse acima sobre os compiladores de 64 bits que preferem as instruções SSE e AVX sobre o FPU (AKA NDP) é absolutamente verdadeiro, pelo menos para o Microsoft Visual Studio 2013. No entanto, para as operações de ponto flutuante de precisão dupla que eu estava usando, encontrei na verdade, é mais rápido e, em teoria, mais preciso, usar a FPU. Se for importante para você, sugiro testar várias soluções primeiro, antes de escolher uma abordagem final.
Ao trabalhar em Java, frequentemente utilizo o tipo de dados BigDecimal de precisão arbitrária. É muito fácil e geralmente não se nota a diminuição da velocidade. O cálculo das funções transcendentais com séries infinitas e sqrt usando o método de Newton pode levar um milissegundo ou mais, mas é factível e bastante preciso.
fonte
Eu só deixei isso aqui /programming//a/58006104/860099 (quando você for lá, clique em 'show snippet de código' e execute-o por botão
É um exemplo de JavaScript que mostra claramente que a soma da maior dá um erro maior
fonte