Wow - figo! Grazie. E ho pensato - conta ogni volta. Sì, beh, è logico, puoi già calcolarlo a tempo di compilazione. Quindi, così:
Ma sarebbe più corretto scrivereDBL_MANT_DIG invece di 53.
Caso di guadagno minimo, se tutti i valori del doppio sono frazionari.
1. La tua implementazione è incompleta, può essere utilizzata solo se la gamma di valori possibili è nota in anticipo.
Ecco il codice dell'implementazione completa
union Double
{
double x;
ulong ul;
};
double Ceil (double x)
{
Double dbl;
dbl.x=x;
//--- убираем знакulong uv=dbl.ul & 0x7fffffffffffffff;
//--- значение меньше единицыif(uv<0x3FF0000000000000)
{
//--- ноль возвращаем как естьif(!uv)
return(x);
//--- оставим только знак
dbl.ul &= 0x8000000000000000;
//--- положительные округляем до 1.0if(!dbl.ul)
return(1.0);
//--- отрицательные округляем до -0.0return(dbl.x);
}
//--- полностью целое числоif(uv>=0x4340000000000000)
return(x);
//--- получим знакulong sign=dbl.ul&0x8000000000000000;
//--- IEEE магия (для домашнего изучения)ulong nuv=uv & ~(((ulong)1<<(51-char(uv>>52)))-1);
//--- для положительного значенияif(!sign)
{
dbl.ul=nuv;
//--- добавим единицу, если число не целоеif(nuv!=uv)
dbl.x+=1.0;
}
else
{
//--- для отрицательного просто добавим знак
dbl.ul=nuv|sign;
}
//--- return(dbl.x);
}
2018.08.2716:11:15.014 TestRound (EURUSD,H1) Время выполнения ceil = 6.382 наносекунд, Контрольная сумма = 5071042018.08.2716:11:15.028 TestRound (EURUSD,H1) Время выполнения Ceil = 4.792 наносекунд, Контрольная сумма = 507104
2. Le funzioni auto-scritte sono significativamente più lente delle funzioni incorporate quando vengono compilate per il debug, quando le ottimizzazioni sono disabilitate.
Volevo speculare sul tema: non puoi capire la Russia con la tua mente, ma poi ho rivolto la mia attenzione al tema: implementazioni alternative di funzioni/approcci standard.
In generale, sull'argomento del thread, sono riuscito a implementare un approccio completamente alternativo al disegno su tela. Senza usare la classe CCanvas.
Cioè, non per modificare un insieme separato di funzioni, ma per creare un meccanismo di disegno completo, costituito da un unico blocco.
(Naturalmente, difficilmente posso dimostrare tutto questo nel codice, perché c'è molto codice ed è scritto in modo non standard, ma vorrei dirvi in generale).
Quindi:
1. il blocco (funzione)
void Нарисовать_элемент(int Канвас, int Элемент = 0)
accetta solo 2 parametri - Kanvas e Element.
Kanvas è un oggetto MT,
L'elemento è un disegno.
2. Ogni oggetto MT ha la sua risorsa assegnata. Viene immediatamente caricata nell'"array di pixel" usando ResourceReadImage(); se la risorsa non esiste ancora, viene impostato un flag, che determinerà successivamente la portata del ciclo sul kernel.
3. kernel, che è un array di proprietà di tutti gli elementi. Contiene dati sulle dimensioni degli oggetti e sui colori dei diversi stati. E molti altri dati. Ci sono 235 proprietà in totale per ogni oggetto. Allo stesso tempo, ogni elemento (a seconda del tipo) può contenere da uno a 11 oggetti (non c'è limitazione).
4. Nel blocco Disegno, ogni oggetto implica un "Dettaglio" del disegno. Quindi, il ciclo per oggetto nel kernel, è un ciclo di disegno in cui viene creata un'immagine di ogni Dettaglio. Se una Tela non è ancora stata creata, si fa un ciclo completo su tutti i dettagli di quella sola Tela. L'affiliazione ai Kanva è prescritta nel kernel, per ogni Dettaglio. Cioè, tutti i Kanvase (e le parti) hanno i loro numeri di sequenza. Attraverso questi numeri è possibile disegnare il contenuto dei soli Kanvas richiesti.
4. Se un Kanvas esiste già e la sua immagine è caricata in un array di pixel, e abbiamo bisogno di ridisegnare solo un singolo elemento (su un evento di cambiamento di colore, per esempio), allora l'intervallo del core loop è ristretto ai confini del singolo elemento il cui numero è stato ottenuto dalla funzione di disegno.
Il disegno in sé è semplice. È un ciclo attraverso le celle di una matrice unidimensionale da sinistra a destra. Prima che il ciclo sia impostato:
1. La cella di partenza (punto A).
2. La cella finale (punto B).
3. Passo avanti.
È difficile riassumere in poche parole il funzionamento di un blocco di 1500 linee di codice. È una funzione che cresce e si lucida da 20 mesi. Lo conosco quasi a memoria, il che rende facile continuare a svilupparlo.
Usando il kernel e il focus (mettendo variabili importanti nello scope globale), il blocco acquisisce enormi possibilità. I loro limiti non mi sono ancora visibili.
Quindi questa è l'alternativa all'approccio standard del disegno kanvas.
zy. Se siete interessati ai dettagli, posso spiegarvi.
1. La tua implementazione è incompleta e può essere utilizzata solo se la gamma di valori possibili è nota in anticipo.
Ecco il codice per l'implementazione completa
Grazie ancora una volta per il codice. Sono stato perplesso su queste maschere di bit come il doppio. Si scopre che non è così facile come pensavo prima. Ho leggermente adattato la mia versione alla tua. C'era solo una differenza: la tua versione restituiva ai valori -1>x>0 Ceil(-0.1)= - 0.0, mentre la mia restituiva 0.0. Anche se non so quando può essere utile.
double Ceil(double x)
{
if(x!=x || // если x = NaN(SNaN) т.е. переполнение или ошибка
x> (long)1<<53 || // или число x положительное и превышает максимальную возможную мантиссу, т.е. дробная часть в x точно отсутствует
x<-(long)1<<53) // или число x отрицательное и превышает максимальную возможную мантиссу, т.е. дробная часть в x точно отсутствует return(x);
if(x-(long)x>0) // Если число положительное или дробная часть не равна нулюreturn(long)x+1.0; // добавляем к бездробной части 1elseif(x>-1 && x<0) // Если -1 < x < 0return -0.0; // то возвращаем -0.0elsereturn (double)long(x);
}
Ho scritto uno script (allegato), che conferma l'identità al 100% con la vostra versione. Ma questa variante è più veloce, più compatta e, secondo me, più leggibile.
Notate che non viene creata nemmeno una singola variabile nel corpo della funzione, mentre la vostra versione crea 4 variabili a 8 byte. Forse mi sbaglio?
Risultati quando l'input x ha sempre una parte frazionaria:
2018.08.2718:42:37.616 TestCeil (EURUSD,M1) Время выполнения функции CeilI = 1.321 наносекунд, Контрольная сумма = 5250492895.02018.08.2718:42:37.619 TestCeil (EURUSD,M1) Время выполнения функции CeilN = 1.094 наносекунд, Контрольная сумма = 5250492895.02018.08.2718:42:37.623 TestCeil (EURUSD,M1) Время выполнения функции ceil = 2.962 наносекунд, Контрольная сумма = 5250492895.02018.08.2718:42:37.623 TestCeil (EURUSD,M1) Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать
I risultati quando l'input x ha una parte frazionaria sono rari:
2018.08.2718:49:45.734 TestCeil (EURUSD,M1) Время выполнения функции CeilI = 0.307 наносекунд, Контрольная сумма = 1.15583114403606 e+232018.08.2718:49:45.736 TestCeil (EURUSD,M1) Время выполнения функции CeilN = 0.102 наносекунд, Контрольная сумма = 1.15583114403606 e+232018.08.2718:49:45.738 TestCeil (EURUSD,M1) Время выполнения функции ceil = 1.026 наносекунд, Контрольная сумма = 1.15583114403606 e+232018.08.2718:49:45.738 TestCeil (EURUSD,M1) Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать
Ilyas:
2. Le funzioni auto-scritte sono significativamente più lente di quelle integrate durante la compilazione per il debug, quando le ottimizzazioni sono disabilitate.
Non è chiaro perché la velocità sia necessaria durante il debug. Ma se ne avete davvero bisogno, potete usare il costrutto:
#ifdef _DEBUG x=Ceil(y);
#else x=ceil(y); #endif
E c'è un'altra cosa che non capisco:
Perché la documentazione e l'effettivo DBL_MANT_DIG = 53?
come secondo la stessa Wikipedia= 52. E, come, segue dal tuo codice che anche 52 ?
Wow - figo! Grazie. E ho pensato - conta ogni volta. Sì, beh, è logico, puoi già calcolarlo a tempo di compilazione.
Quindi, così:
Ma sarebbe più corretto scrivereDBL_MANT_DIG invece di 53.
Caso di guadagno minimo, se tutti i valori del doppio sono frazionari.
1. La tua implementazione è incompleta, può essere utilizzata solo se la gamma di valori possibili è nota in anticipo.
Ecco il codice dell'implementazione completa
2. Le funzioni auto-scritte sono significativamente più lente delle funzioni incorporate quando vengono compilate per il debug, quando le ottimizzazioni sono disabilitate.
1. La tua implementazione è incompleta e può essere utilizzata solo se la gamma di valori possibili è nota in anticipo.
Ecco il codice per l'implementazione completa
2. Le funzioni auto-scritte sono molto più lente di quelle integrate durante la compilazione per il debug quando le ottimizzazioni sono disabilitate.
Grazie mille, Ilyas, per il codice eccellente.
Naturalmente, è un grande aiuto in questo caso.
Lo sto studiando.
Non è la stessa cosa?Nikolai, ciao. Vedo che stai lavorando sulla grafica, ma non capisco bene quale sia il compito effettivo. A cosa stai lavorando?
Accelerare le funzioni di rendering?
In generale, sull'argomento del thread, sono riuscito a implementare un approccio completamente alternativo al disegno su tela. Senza usare la classe CCanvas.
Cioè, non per modificare un insieme separato di funzioni, ma per creare un meccanismo di disegno completo, costituito da un unico blocco.
(Naturalmente, difficilmente posso dimostrare tutto questo nel codice, perché c'è molto codice ed è scritto in modo non standard, ma vorrei dirvi in generale).
Quindi:
1. il blocco (funzione)
accetta solo 2 parametri - Kanvas e Element.
2. Ogni oggetto MT ha la sua risorsa assegnata. Viene immediatamente caricata nell'"array di pixel" usando ResourceReadImage(); se la risorsa non esiste ancora, viene impostato un flag, che determinerà successivamente la portata del ciclo sul kernel.
3. kernel, che è un array di proprietà di tutti gli elementi. Contiene dati sulle dimensioni degli oggetti e sui colori dei diversi stati. E molti altri dati. Ci sono 235 proprietà in totale per ogni oggetto. Allo stesso tempo, ogni elemento (a seconda del tipo) può contenere da uno a 11 oggetti (non c'è limitazione).
4. Nel blocco Disegno, ogni oggetto implica un "Dettaglio" del disegno. Quindi, il ciclo per oggetto nel kernel, è un ciclo di disegno in cui viene creata un'immagine di ogni Dettaglio. Se una Tela non è ancora stata creata, si fa un ciclo completo su tutti i dettagli di quella sola Tela. L'affiliazione ai Kanva è prescritta nel kernel, per ogni Dettaglio. Cioè, tutti i Kanvase (e le parti) hanno i loro numeri di sequenza. Attraverso questi numeri è possibile disegnare il contenuto dei soli Kanvas richiesti.
4. Se un Kanvas esiste già e la sua immagine è caricata in un array di pixel, e abbiamo bisogno di ridisegnare solo un singolo elemento (su un evento di cambiamento di colore, per esempio), allora l'intervallo del core loop è ristretto ai confini del singolo elemento il cui numero è stato ottenuto dalla funzione di disegno.
Il disegno in sé è semplice. È un ciclo attraverso le celle di una matrice unidimensionale da sinistra a destra. Prima che il ciclo sia impostato:
1. La cella di partenza (punto A).
2. La cella finale (punto B).
3. Passo avanti.
È difficile riassumere in poche parole il funzionamento di un blocco di 1500 linee di codice. È una funzione che cresce e si lucida da 20 mesi. Lo conosco quasi a memoria, il che rende facile continuare a svilupparlo.
Usando il kernel e il focus (mettendo variabili importanti nello scope globale), il blocco acquisisce enormi possibilità. I loro limiti non mi sono ancora visibili.
Quindi questa è l'alternativa all'approccio standard del disegno kanvas.
zy. Se siete interessati ai dettagli, posso spiegarvi.
Ecco come appare l'inizio del blocco:
1. La tua implementazione è incompleta e può essere utilizzata solo se la gamma di valori possibili è nota in anticipo.
Ecco il codice per l'implementazione completa
Grazie ancora una volta per il codice. Sono stato perplesso su queste maschere di bit come il doppio. Si scopre che non è così facile come pensavo prima.
Ho leggermente adattato la mia versione alla tua. C'era solo una differenza: la tua versione restituiva ai valori -1>x>0 Ceil(-0.1)= - 0.0, mentre la mia restituiva 0.0. Anche se non so quando può essere utile.
E si ottiene quanto segue:
Stessa cosa, solo leggibile e con commenti:
Ho scritto uno script (allegato), che conferma l'identità al 100% con la vostra versione.
Ma questa variante è più veloce, più compatta e, secondo me, più leggibile.
Notate che non viene creata nemmeno una singola variabile nel corpo della funzione, mentre la vostra versione crea 4 variabili a 8 byte.
Forse mi sbaglio?
Risultati quando l'input x ha sempre una parte frazionaria:
I risultati quando l'input x ha una parte frazionaria sono rari:
2. Le funzioni auto-scritte sono significativamente più lente di quelle integrate durante la compilazione per il debug, quando le ottimizzazioni sono disabilitate.
Non è chiaro perché la velocità sia necessaria durante il debug.
Ma se ne avete davvero bisogno, potete usare il costrutto:
E c'è un'altra cosa che non capisco:
Perché la documentazione e l'effettivo DBL_MANT_DIG = 53?
come secondo la stessa Wikipedia= 52.
E, come, segue dal tuo codice che anche 52 ?
Nikolai, ciao. Vedo che stai lavorando sulla grafica, ma non capisco bene quale sia il compito effettivo. A cosa stai lavorando?
Accelerare le funzioni di rendering?
Ciao Piotr!
Ti risponderò di persona.
E c'è un'altra cosa che non capisco:
Perché la documentazione e l'effettivo DBL_MANT_DIG = 53?
mentre secondo la stessa wikipedia= 52.
E sembra che il tuo codice implichi anche che sia 52?
Hai provato a trovare la risposta alla domanda da solo?
Suggerimento: nella ricerca su Google, digitate "DBL_MANT_DIG 53 52".