Se você precisar de uma função personalizada para obter exatamente a mesma string mais curta que o cast (string)dbl, use a função Repr() da biblioteca:
string shortest_str = Repr(dbl) .
Essa função já foi necessária antes de os desenvolvedores de MQL corrigirem o erro com string e Print() para estar em conformidade com o padrão ieee-754.
Gostaria que você estivesse certo e que fosse tão simples assim. Eu não estaria aqui se fosse tão fácil e definitivamente não estaria perdendo tantas horas de trabalho com isso.
É verdade que eu preciso:
1. controlar o número de dígitos após o ponto decimal
2. ajustar dinamicamente o número de dígitos e torná-lo o mais curto possível
Nada de estranho, valores padrão, tudo certo, mas LotValue parece ser difícil de formatar e mostrar na tela.
O GRANDE problema é que minhas duplas aparecem como 1.000000000, mas na verdade são 1.000000001
(Eu sei como funcionam as duplas e entendo que isso é normal)
Print(), DoubleToString(), NormalizeDoubles() e StringFormat() basicamente arredondam o número e o número resultante está terrivelmente errado; nada funcionou, a precisão desejada simplesmente não foi alcançada com as funções MQL4 incorporadas porque elas arredondam o número, e 1.000000000 acabou sendo igual a 1.1
(não consigo pensar em nenhuma circunstância em que seja conveniente para um aplicativo que mostra constantemente os preços ver um número "falso" transformado de 1,04966 para 1,0497, mas essa é uma discussão para outro dia)
É por isso que, no início, eu estava usando uma fórmula simples para obter a precisão desejada
int p = 5; // precisão desejadadouble n = 1.000000000;
double p10 = (p * 10);
double(long(n * p10) / p10);
Mas a situação se complica quando, em vez de Forex, eu uso criptomoedas, onde preciso de uma precisão maior, de 9 a 10, e, acima disso, não consegui remover os zeros finais, então cheguei às suas funções.
E todo esse problema ocorre porque preciso enviar ao usuário o máximo de informações possível e o espaço na tela é limitado, por isso preciso comprimir o número em um espaço fixo.
Sua função Trunc() dá conta do recado para 99,9% dos números, mas há alguns que não cooperam e precisam de um tratamento especial.
Eu esperava que você pudesse fornecer uma fórmula reduzida para fazer isso.
E agora, aumentando meus problemas, a função Round(double, int) interrompe a execução do MT4 com alguns números duplos. Não consigo entender por que, pois o double não é tão grande, sendo 100000.0000000000
É um número comum que representa o valor de 1 lote para EURUSD e, se eu escrever o valor à mão, tudo fica bem, mas se ele vier da matemática LotValue = ((TickValue / TickSize) * lot); o MT4 bloqueia.
É uma tarefa tão simples e já gastei mais de 40 horas nisso. Isso está me matando!
1. controlar o número de dígitos após o ponto decimal
2. ajustar dinamicamente o número de dígitos e torná-lo o mais curto possível
Eu lhe disse
double n = 1.000000000;
É o mesmo que:
double n = 1.0;
Seu requisito:
decimais na string <= dígitos_especificados
Se o seu único requisito for formatar o número em uma cadeia de caracteres tão curta quanto possível, sem 0s à direita (enquanto controla o número máximo de dígitos decimais):
Round e NormalizeDouble controlarão o máximo de dígitos decimais. Em seguida, a conversão para string (string)dbl obterá a string mais curta possível sem os zeros finais. StringFormat() faz a mesma coisa, mas parece ser um pouco mais lento se for chamado milhões de vezes em seu código.
No seu caso, DoubleToString() não é aconselhável, pois ele preencherá as cadeias de caracteres mais curtas < dígitos com 0s finais para manter um número fixo de dígitos decimais. Não é isso que você está pedindo. Você está solicitando um número dinâmico de dígitos decimais (o mais curto).
Parece que, depois de quatro mensagens, não consegui fazer com que você entendesse meu problema, e estou muito decepcionado com meu fracasso.
E o estilizador deste site está completamente danificado, por isso é muito demorado escrever uma mensagem corretamente aqui
double n = 1.000000000;
should be the same as:
double n = 1.0;
but it is NOT
Não sei explicar o motivo, mas devemos presumir que 1.000000000; tem um decimal diferente de 0 em algum lugar, embora graficamente eu não tenha conseguido gerar isso.
Mas os resultados são esses:
string s1 = (string) Round(number, digits); -> blocks MT4
string s2 = (string) NormalizeDouble(number, digits); -> returns a 'faked' string where a rounding is done on last digit
string s3 = StringFormat("%.5f", number); -> same asNormalizeDouble()
para números como 19,65400
string s = (string) Trunc(number, digits);
funciona perfeitamente. E se eu inserir manualmente 1,0000000, ele ainda funcionará perfeitamente.
Para que você me entenda, eu uso a função em mais de 400 parâmetros diferentes e cada um deles tem um valor diferente em cada tick e Trunc() funciona perfeitamente.
não funciona, e é por isso que também incluí a função Round(number, digits); e ela costumava fazer o truque, e decidi simplesmente perguntar se havia uma fórmula para combinar minha função Normalize_Double_ToString() em um código mais simples e otimizado.
E você me respondeu algo muito diferente (presumo que a culpa seja inteiramente minha por não ter explicado corretamente)
Mas desde ontem o Round() bloqueia o MT4 e, sem o Round, não consigo contar corretamente os dígitos significativos no lado dos decimais.
O problema parece ser o typecasting to long. Se eu removê-lo de Round(double, int); o MT4 executa sem problemas, mas não consigo entender como um double com 6 dígitos inteiros, multiplicado por 10.000, atinge os limites de long.
Acho que, neste ponto, minha pergunta é:
Onde está a saída?
De qualquer forma, vou ter que deixar isso de lado e voltarei ao assunto em algumas semanas.
Parece que, depois de quatro mensagens, não consegui fazer com que você entendesse meu problema, e me sinto terrivelmente decepcionado com meu fracasso.
Além disso, o estilizador deste site está completamente danificado, por isso é muito demorado escrever uma mensagem corretamente aqui
Não sei explicar o motivo, mas devemos presumir que 1.000000000; tem um decimal diferente de 0 em algum lugar, embora graficamente eu não tenha conseguido mostrar isso.
Tenho certeza de que entendi a causa de seus problemas no MT4.
O principal motivo pelo qual você não consegue obter os resultados esperados é um erro na string(dbl) da MQL4 que ainda não foi corrigido no MT4.
Erro na função string() da MQL4. Conversão incorreta de double -> string.
Isso também afeta a forma como os duplos são exibidos (por meio da conversão implícita para string) por Print(), Alert(), Comment(), FileWrite().
Se você quiser se aprofundar ou depurar suas duplas como string no MT4, sempre force a conversão explícita para string por meio da função Repr() do math_utils.mqh
#include "math_utils.mqh"//+------------------------------------------------------------------+//||//+------------------------------------------------------------------+voidOnStart()
{
double a = 1.0000000000000002;
Print(a); // 1.0 (bug na conversão implícita double -> string)Print(Repr(a)); // 1.0000000000000002double b = 100.00000000000003;
Print(b); // 100,0 (erro na conversão implícita double -> string)Print(Repr(b)); // 100.00000000000003
}
On indicators, mt5 can set automatically a level "0" depending of the buffer values. Custom indicator showing zero level, though not defined anywhere in the code. Wrong conversion of double -> string. Then test the same example in your browser js pad or any online javascript pad and check the difference
Gostaria que você estivesse certo e que fosse tão simples assim. Eu não estaria aqui se fosse tão fácil e definitivamente não estaria perdendo tantas horas de trabalho com isso.
É verdade que eu preciso:
1. controlar o número de dígitos após o ponto decimal
2. ajustar dinamicamente o número de dígitos e torná-lo o mais curto possível
Meus dígitos duplos vêm de
Tickvalue -> SYMBOL_TRADE_TICK_VALUE
TickSize -> SYMBOL_TRADE_TICK_SIZE
e
LotValue = ((TickValue / TickSize) * lot);
Nada de estranho, valores padrão, tudo certo, mas LotValue parece ser difícil de formatar e mostrar na tela.
O GRANDE problema é que minhas duplas aparecem como 1.000000000, mas na verdade são 1.000000001
(Eu sei como funcionam as duplas e entendo que isso é normal)
Print(), DoubleToString(), NormalizeDoubles() e StringFormat() basicamente arredondam o número e o número resultante está terrivelmente errado; nada funcionou, a precisão desejada simplesmente não foi alcançada com as funções MQL4 incorporadas porque elas arredondam o número, e 1.000000000 acabou sendo igual a 1.1
(não consigo pensar em nenhuma circunstância em que seja conveniente para um aplicativo que mostra constantemente os preços ver um número "falso" transformado de 1,04966 para 1,0497, mas essa é uma discussão para outro dia)
É por isso que, no início, eu estava usando uma fórmula simples para obter a precisão desejada
Mas a situação se complica quando, em vez de Forex, eu uso criptomoedas, onde preciso de uma precisão maior, de 9 a 10, e, acima disso, não consegui remover os zeros finais, então cheguei às suas funções.
E todo esse problema ocorre porque preciso enviar ao usuário o máximo de informações possível e o espaço na tela é limitado, por isso preciso comprimir o número em um espaço fixo.
Sua função Trunc() dá conta do recado para 99,9% dos números, mas há alguns que não cooperam e precisam de um tratamento especial.
Eu esperava que você pudesse fornecer uma fórmula reduzida para fazer isso.
E agora, aumentando meus problemas, a função Round(double, int) interrompe a execução do MT4 com alguns números duplos. Não consigo entender por que, pois o double não é tão grande, sendo 100000.0000000000
É um número comum que representa o valor de 1 lote para EURUSD e, se eu escrever o valor à mão, tudo fica bem, mas se ele vier da matemática LotValue = ((TickValue / TickSize) * lot); o MT4 bloqueia.
É uma tarefa tão simples e já gastei mais de 40 horas nisso. Isso está me matando!
É verdade que eu preciso:
1. controlar o número de dígitos após o ponto decimal
2. ajustar dinamicamente o número de dígitos e torná-lo o mais curto possível
Parece que, depois de quatro mensagens, não consegui fazer com que você entendesse meu problema, e estou muito decepcionado com meu fracasso.
E o estilizador deste site está completamente danificado, por isso é muito demorado escrever uma mensagem corretamente aqui
Não sei explicar o motivo, mas devemos presumir que 1.000000000; tem um decimal diferente de 0 em algum lugar, embora graficamente eu não tenha conseguido gerar isso.
Mas os resultados são esses:
para números como 19,65400
funciona perfeitamente. E se eu inserir manualmente 1,0000000, ele ainda funcionará perfeitamente.
Para que você me entenda, eu uso a função em mais de 400 parâmetros diferentes e cada um deles tem um valor diferente em cada tick e Trunc() funciona perfeitamente.
Mas para:
double lotValue = ((_TickValue / _TickSize) * lot);não funciona, e é por isso que também incluí a função Round(number, digits); e ela costumava fazer o truque, e decidi simplesmente perguntar se havia uma fórmula para combinar minha função Normalize_Double_ToString() em um código mais simples e otimizado.
E você me respondeu algo muito diferente (presumo que a culpa seja inteiramente minha por não ter explicado corretamente)
Mas desde ontem o Round() bloqueia o MT4 e, sem o Round, não consigo contar corretamente os dígitos significativos no lado dos decimais.
O problema parece ser o typecasting to long. Se eu removê-lo de Round(double, int); o MT4 executa sem problemas, mas não consigo entender como um double com 6 dígitos inteiros, multiplicado por 10.000, atinge os limites de long.
Acho que, neste ponto, minha pergunta é:
Onde está a saída?
De qualquer forma, vou ter que deixar isso de lado e voltarei ao assunto em algumas semanas.
Tente isso:
No entanto, ele não será muito melhor do que os três métodos mais curtos da postagem anterior.
Observação,
Eu uso Round() da minha biblioteca, não o método errado que você postou antes, ou uso:
n = NormalizeDouble(n, d);
Mas duvido que você tenha dito que Round() tenha erros.Parece que, depois de quatro mensagens, não consegui fazer com que você entendesse meu problema, e me sinto terrivelmente decepcionado com meu fracasso.
Além disso, o estilizador deste site está completamente danificado, por isso é muito demorado escrever uma mensagem corretamente aqui
Não sei explicar o motivo, mas devemos presumir que 1.000000000; tem um decimal diferente de 0 em algum lugar, embora graficamente eu não tenha conseguido mostrar isso.
Tenho certeza de que entendi a causa de seus problemas no MT4.
O principal motivo pelo qual você não consegue obter os resultados esperados é um erro na string(dbl) da MQL4 que ainda não foi corrigido no MT4.
Erro na função string() da MQL4. Conversão incorreta de double -> string.
O erro foi corrigido no MT5, mas não no MT4. Veja aqui: https: //www.mql5.com/en/forum/367839/page3#comment_27477157 e a correção aqui: https: //www.mql5.com/en/forum/367839/page5#comment_27613205
Minha recomendação:
Se você quiser se aprofundar ou depurar suas duplas como string no MT4, sempre force a conversão explícita para string por meio da função Repr() do math_utils.mqh