Velocidade de execução das funções ceil(),round(),floor() - página 6

 
Nikolai Semko:

Eu já escrevi sobre isso aqui.

ok. Como entendo que você está escrevendo dentro deste terminal e dentro da precisão dada, você não está interessado em portar e executar o código em qualquer outro dispositivo ou plataforma.

Com os melhores cumprimentos.

P.S. Um bom programador deve entender que o hardware e o programa podem mudar e você precisa evitar bugs no futuro.
 
Andrey Kisselyov:
Se você estiver escrevendo dentro dos limites do terminal dado e dentro dos limites de sua precisão, a portabilidade e operação do código em qualquer outro dispositivo ou plataforma não é de seu interesse.

Sinceramente.

Exatamente. Estamos falando da MQL5 (talvez também da MQL4 - ainda não verifiquei). E o código dentro das classes ou algoritmos será perfeitamente portátil dentro do MQL. Mas também funcionará em C++. Eu já tenho alguns exemplos.

 
Andrey Kisselyov:

P.S. Um bom programador deve entender que o hardware e o programa podem mudar e é necessário evitar erros no futuro. Com uma tarefa como a sua, você pode não ser capaz de encontrar facilmente um erro em uma função que você considerará infalível naquele momento.
Nesta situação, é impossível sequer imaginar as mudanças de que se está falando. O que pode mudar com a matemática de cálculo (int)(x+0,5)? Parará de descartar a parte fracionária ou o quê?
 
Nikolai Semko:
Nesta situação, é impossível sequer imaginar as mudanças de que você está falando. O que pode mudar com a matemática de cálculo (int)(x+0,5)? Será que vai parar de soltar a parte fracionária?

Por exemplo, um novo tipo de dados será introduzido ...

 
STARIJ:

Por exemplo, um novo tipo de dados será introduzido ...

))) Sim, mas o código deixará de funcionar se o tipo de dados antigo for cancelado....
 
Estou falando desta confusão.
y=(int)(x+0.9999999999999997);

Vamos tomar como exemplo:
Se você mudar até mesmo o bitness da máquina, você muda para 64 bits e a precisão da máquina aumentou, sua fórmula deixará de funcionar, pois a precisão da máquina será muito maior do que você está ajustando em seu erro.

Com todo respeito.

P.S. pode haver outras opções onde sua fórmula falhará em uma gama de números. erro de ajuste constante de mudança para uma máquina diferente, ou mudanças no compilador, que você não é informado, ou quando você muda a representação dos números na máquina, ou de cortar uma parte fracionada do número ao compilar uma nova versão do terminal ... Você não sabe o que pode mudar, e não acho que seja uma boa idéia fazer um SE ou sofrer para adivinhar o que vai acontecer ao escrever um erro uma e outra vez...

Acho que há muito o que pensar.

 
Andrey Kisselyov:

...

P.S. duplo por definição não pode ser um número inteiro, a representação de um número na memória da máquina não mudará.

Talvez você esteja dizendo que duplo não é um tipo de dado inteiro, não que você não pode armazenar um número com um valor inteiro em uma variável do tipo duplo? Um número inteiro duplo pode ser um número inteiro.

 

Encontramos uma explicação simples da diferença entre arredondamento implementado em computadores e simples truncagem pós-pick. Catorze anos de idade, http://delphimaster.net/view/14-10885/all:

Tolik(2003-08-13 11:04) [11].

Tal arredondamento é aceito na contabilidade. Portanto, o fisco também aplica este arredondamento, portanto tudo deve somar, pelo menos no papel :)))



DiamondShark(2003-08-13 11:20) [12]

Oh-ho-ho... Novamente.
Suponha que tenhamos uma distribuição de números próxima a uniformemente aleatória. Em seguida, por arredondamento "aritmético" que temos:

O número Incerteza
0 0
1 -1
2 -2
3 -3
4 -4
5 +5
6 +4
7 +3
8 +2
9 +1

Como pode ser facilmente visto, se houver uma grande variedade de números que precisam ser somados (totais para itens de documentos, saldos de contas, etc.), então o arredondamento "aritmético" acumulará um erro sistemático com a expectativa
0,5*10^n * 0,1 * N
onde:
n -- peso decimal do dígito ao qual o arredondamento é realizado (para dois dígitos n=-2, para números inteiros n=0, etc.)
0,1 é a probabilidade de cada dígito
N é um número de números inteiros em uma série

A fim de equalizar as probabilidades de erro é necessário compensar o único erro não compensado (ver tabela acima) +5. Isto é feito dividindo-o artificialmente em dois, igualmente prováveis +5 -5, dependendo da paridade do dígito anterior.

A propósito, há uma caixa de seleção na palavra de status da FPU que controla o modo de arredondamento (aritmética/contabilidade).


Fim da citação.

Outro, http://delphimaster.net/view/15-1340952214/all:"como o usuário médio (gerente/contador) não pode explicar porque arredondar 12,5 e 13,5 - dá resultados diferentes".


Ao dar ao usuário versões "aceleradas" de funções de arredondamento, é preciso ser fortemente advertido de que elas dão origem a um erro maior ao adicionar. Este erro terá que ser cuidadosamente avaliado em situações muito diferentes. É perigoso, está repleto de erros acumulados. Acho difícil pensar em um exemplo em que o arredondamento é tão importante que você pode esquecer os erros que ele acumula.

Округление чисел. Неужели ТАК правильно???
  • delphimaster.net
3-10545           Kati                  2003-08-12 10:13  2003.09.04   обновление SQL запроса 14-10898          kalishenko            2003-08-14 20:09  2003.09.04   Win2000 Server и доступ в Интернет 1-10692           lww                   2003-08-20 10:30  2003.09.04   Как написать dll для 1С? 1-10813           koks                  2003-08-20...
 

Andrey Kisselyov:
я говорю про вот это безобразие

y=(int)(x+0.9999999999999997);

Muito bem, senhores, vocês já se manifestaram. Mudarei a função de tetos especialmente para você:

y=ceil(x);  ->  y=(x-(int)x>0)?(int)x+1:(int)x;
или через дефайн:
#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x

Esta variante é 25-50% mais lenta do que a variante:y=(int)(x+0,99999999999999999997); mas é maximamente correta, funciona para números inteiros negativos e é 3 vezes mais rápida do que o ceil(x).

Mas eu, como cidadão comum e fracassado, vou usar a variante com noves, porque considero todos os seus argumentos chatos e para mim, alguém que tem programado em assembler há muito tempo, e portanto sabe o que acontece com o código após a compilação, é demais - colocar cheques onde você pode passar sem eles.

 

Uma variante para números positivos e negativos:

#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x
#define _round(x) (x>0)?(int)(x+0.5):(int)(x-0.5)
#define _floor(x) (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x
Isto parece ser um substituto completo para o ceil(),round(),floor(), o que dá uma vantagem de velocidade de 3-4 vezes.
Razão: