Implementações alternativas de funções/abordagens padrão - página 10

 
pavlick_:
)). Isto pode ter um lugar somente em artesanato pessoal com conhecimento exato da faixa de valores, mas não na biblioteca std. As funções embutidas não são escritas por tolos, não pense que você é o mais inteligente. Aqui está um amigo que também escreve um comportamento indefinido e não especificado e depois se surpreende que não funcione dessa maneira https://www.linux.org.ru/forum/development/14422428#comments. Todas essas economias de alguns nanossegundos não serão visíveis nem mesmo em algoritmo real (não em loop nu).

Só agora eu peguei o que você estava dizendo.
Retiro que você não está no circuito. Peço desculpas.
Sim, você pode usar essa variante com a condição de que o dobro do número esteja na faixa de -900719999254740992 a 9007199254740992 (2 até a potência de 53 (número de bits na mantissa))

 
Renat Fatkhullin:
Pense no que você vai obter fora da faixa inteira.

Que tal isso?

double Ceil (double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}

resultado:

2018.08.26 10:49:23.552 TestRound (Crypto.ALT,M10)      Время цикла без округления = 1.317 наносекунд, сумма = 115583114403605978808320.00000000
2018.08.26 10:49:23.556 TestRound (Crypto.ALT,M10)      Время выполнения функции ceil =  2.129 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.557 TestRound (Crypto.ALT,M10)      Время выполнения функции Ceil =  0.100 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.560 TestRound (Crypto.ALT,M10)      Время выполнения функции floor = 1.299 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.561 TestRound (Crypto.ALT,M10)      Время выполнения функции Floor = 0.120 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.564 TestRound (Crypto.ALT,M10)      Время выполнения функции round = 1.787 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Время выполнения функции Round = 0.106 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать

o teste parece mostrar uma identidade completa.

Entretanto, a velocidade da solução alternativa neste caso, onde há uma verificação de alcance, é mais alta em cerca de 2 vezes (ao invés de 3-8), mas isto se o número duplo estiver na faixa de-9007199254740992 a 9007199254740992. Mas é muito mais alto quando está fora desta faixa.

Arquivos anexados:
TestRound.mq5  9 kb
 
Nikolai Semko:


o teste parece mostrar uma identidade completa.

No entanto, esta variante não leva em conta o excesso de variável de entradado tipo duplo, quando toma valores nan, snan.

Se tiver que ser levado em conta, você pode adicionar mais uma verificação, mas ainda assim esta variante funcionará mais rapidamente do que a função original

double Ceil (double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}
 
Nikolai Semko:

Escreva um EA para um testador/optimista. É aí que a velocidade na prática é importante.

 
fxsaber:

Escreva um EA para um testador/optimista. É aí que a velocidade é importante na prática.

Como muitas pessoas sabem, eu também faço gráficos suaves. É para suavizar os gráficos e trabalhar com cada pixel que as funções de arredondamento são ativamente utilizadas.

Antes eu não podia sequer imaginar que a função de arredondamento fosse mais lenta do que a extração da raiz quadrada do duplo.
É por esta razão que eu levei a sufocar aqueles nanossegundos. Porque aqueles nanossegundos no gráfico alisado podem se transformar em milissegundos em cada quadro, e um quadro pode mudar a cada 33 milissegundos.

 
Nikolai Semko:

Como muitas pessoas sabem, eu também lido com gráficos anti-aliased. É para gráficos anti-aliased e trabalhar com cada pixel que as funções de arredondamento são utilizadas ativamente.
É por esta razão que me empenhei em suavizar esses nanossegundos. Porque aqueles nanossegundos nos gráficos suavizados podem se transformar em milissegundos em cada quadro, e um quadro pode mudar a cada 33 milissegundos.

Naturalmente, isto é importante para os gráficos. É por isso que as otimizações algorítmicas para quase todas as tarefas comuns já existem há muito tempo.

 
fxsaber:

Naturalmente, isto é importante para os gráficos. É por isso que as otimizações algorítmicas para quase todas as tarefas comuns já existem há muito tempo.

Você está enganado. O campo ainda não está arado, e o que está arado está fechado. E ainda mais na MQL. A classe CCanvas está muito longe da otimização e quase não há antialiasing e o que há de antialiasing é insatisfatório.

 

Por que você não usa LONG_MAX/MIN? De alguma forma, ficaria mais bonito. Acho que fica bonito. Fiz seus testes com o gcc (com modificações mínimas, é claro, com o compilador muito antigo 5.4.0, o que eu tinha em mãos):

1. Compilação com -O3.

Время цикла без округления = 0.001099185 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.004310106 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.001912712 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.005283493 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.002031304 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.005308409 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.002344382 секунд, сумма = 1.15583114 e+23

2. Compilação com -Ofast

Время цикла без округления = 0.000552652 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.001720999 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.00189282 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.001430063 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.001979336 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.001698521 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.001944874 секунд, сумма = 1.15583114 e+23

Seu código tem um problema com cálculo de tempo - saída em milissegundos (não nano), e eu ainda não entendo porque você precisa de menos t0.

Print("Время выполнения функции ceil =  "+DoubleToString((double)(GetMicrosecondCount()-t-t0)/1000,3)+" наносекунд, Контрольная сумма = "+string(s));
 
Nikolai Semko:

Errado. Ainda há um campo não lavrado, e o que é lavrado está fechado.

Eu estava falando de experiência mundial. Veja os algoritmos nos fóruns temáticos onde eles fazem demonstrações gráficas. As pessoas estão compartilhando seus algoritmos rápidos.

 
fxsaber:

Eu estava falando de experiência mundial. Procure por algoritmos nos fóruns temáticos onde são feitas as demonstrações gráficas. As pessoas estão compartilhando algoritmos rápidos.

Você pode, por favor, me enviar o link?