ceil(), round(), floor() fonksiyonlarının yürütme hızı - sayfa 4

 
Alexey Navoykov :

Yani DBL_EPSILON 16 ondalık basamaktır: 2.2204460492503131e-016

Ve senin durumunda, aslında bir olduğu ortaya çıkıyor, çünkü. fark sadece 1e-16, yani epsilon'dan 2 kat daha az.


0.99999999999999997 ile çalışır, ancak 0.99999999999999998 ile çalışmaz.

 
Nikolai Semko :

0.99999999999999997 ile çalışır, ancak 0.99999999999999998 ile çalışmaz.


İşte başka bir şaka:

Y=( int )(x+ 1 - 2 * DBL_EPSILON );
Print (Y);                              // 3
Y=( int )(x+ 1 - DBL_EPSILON - DBL_EPSILON );
Print (Y);                              // 4
 

Ondalık gösterimdeki 2.2204460492503131e-016 sayısı, çift biçimin çözünürlüğü anlamına gelir ( https://msdn.microsoft.com/en-us/library/6bs3y5ya(v=vs.100).aspx ), bu

En küçük pozitif sayı x, öyle ki x + 1.0, 1.0'a eşit değil.

1.0 eklenmesi sayının değerini değiştirecek şekilde en küçük pozitif sayıdır. Başka bir deyişle, bu bir sayının temsilindeki göreli hatadır. Yani, 16 için bu sınır çok fazla ondalık dokuz içerecek ve sonunda 64 için 1'den 4 kat daha fazla bir fark olacak, 8 için iki kat daha az olacak. Bu nedenle, mümkün olan en yüksek doğrulukla yuvarlamayı hızlandırmak için bu doğruluğun hesaplanması gerekecektir. Bu hesaplamaların normal yuvarlama işlevlerinin yürütülmesinden daha hızlı gerçekleşmesi olası değildir. MQL, sayıların adresleriyle doğrudan çalışmanıza izin vermediğinden, sayıdaki sipariş bitlerini almak mümkün olmayacaktır, taban 2'de log fonksiyonunun bir analogunu bulmanız gerekecektir. hızlı bir şekilde.

Пределы констант с плавающей запятой
Пределы констант с плавающей запятой
  • msdn.microsoft.com
В следующей таблице представлены ограничения на значения констант с плавающей запятой. Эти ограничения также заданы в стандартном файле заголовка FLOAT.H. Ограничения на константы с плавающей запятой КонстантаЗначениеЗначение Количество цифр q, при котором число с плавающей запятой с q десятичными цифрами можно округлить в представление с...
 
Nikolai Semko :

İşte başka bir şaka:

Herhangi bir matematiksel eylemin hem olumlu hem de olumsuz olabilen ek bir hata getirdiği ortaya çıktı. Bu nedenle, genel durumda, Vladimir'in belirttiği gibi, sonucu normalleştirmek gerekir.

 

ceil(), floor()'ın tekrarlanması olası değildir, çünkü FPU yuvarlama modu µl'den kontrol edilemez. Muhtemelen aşağı yukarı yeterince çalışacak tek şey round() ve bu tam olarak standarda göre değil. Bu arada, C'nin round() şuna benziyor:

 double round ( double x)
{
    fenv_t save_env;
    feholdexcept(&save_env);
     double result = rint(x);
     if (fetestexcept(FE_INEXACT)) {
        fesetround(FE_TOWARDZERO);
        result = rint(copysign( 0.5 + fabs (x), x));
    }
    feupdateenv(&save_env);
     return result;
}
 
Burada neyi yuvarlamak istediğinizi anlamak için, DOUBLE formatını INT formatına dönüştürürken tam olarak nasıl ve neyin kaybolduğunu bilmeniz gerekir. bu durumda, kesimden sonra kalan sadece bir kısmını alırsınız. sonuç olarak, herhangi bir sayıda ondalık basamaklı herhangi bir sayı ve ondalık noktadan sonraki herhangi bir basamak silinecek ve yalnızca tamsayı kısmı kalacaktır.
misal:
 2.1758716871 -> ( int ) 2.1758716871 = 2
2.0000000001 -> ( int ) 2.0000000001 = 2
2.9999999999 -> ( int ) 2.9999999999 = 2
buna sayı biçimi değiştiğinde kesinlik kaybı denir.
Sonuç olarak
 MathFloor (x)  =  ( int )(x)
MathCeil (x)   =  ( int )(x)+ 1 ;
MathRound (x)  =  ( int )(x+0.5)

Samimi olarak.
 
Andrey Kisselyov :
Burada neyi yuvarlamak istediğinizi anlamak için, DOUBLE formatını INT formatına dönüştürürken tam olarak nasıl ve neyin kaybolduğunu bilmeniz gerekir. bu durumda, kesimden sonra kalan sadece bir kısmını alırsınız. sonuç olarak, herhangi bir sayıda ondalık basamaklı herhangi bir sayı ve ondalık noktadan sonraki herhangi bir basamak silinecek ve yalnızca tamsayı kısmı kalacaktır.
örnek: buna sayı biçimini değiştirirken kesinlik kaybı denir.
Sonuç olarak

Samimi olarak.

Neden bu kadar zor:

 MathRound (x)  - >  ( int )(x)+( int )( 2 .*(x-( int )(x)));

Bu seçenek neden daha basit olandan daha iyi?

 MathRound (x)  ->  ( int )(x+ 0.5 );
 
Alexey Navoykov :

Herhangi bir matematiksel eylemin hem olumlu hem de olumsuz olabilen ek bir hata getirdiği ortaya çıktı. Bu nedenle, genel durumda, Vladimir'in belirttiği gibi, elde edilen sonucun normalleştirilmesi gerekir.


pavlick_ :

ceil(), floor()'ın tekrarlanması olası değildir, çünkü FPU yuvarlama modu µl'den kontrol edilemez. Muhtemelen az çok yeterli şekilde çalışacak tek şey yuvarlak ()'dir ve bu tam olarak standarda uygun değildir. Bu arada, C'nin round() şuna benziyor:


Elbette haklısın. Ama tekrar edeceğim. Görevlerin %99,9'u için, yuvarlama işlevlerini (int) veya (long)'a kesirli tür dönüştürmeyi kullanarak alternatif daha hızlı bir seçenekle değiştirmek kesinlikle yasaldır. Deneyimli bir programcının bu gerçeğin farkında olması ve uygun olduğunda uygulaması yeterlidir.

 Для положительных x:
y= floor (x); -> y=( int )x;
y= ceil (x);  -> y=( int )(x+ 0.9999999999999997 );
y= round (x); -> y=( int )(x+ 0.5 );
 
Nikolai Semko :

Neden bu kadar zor:

Bu seçenek neden daha basit olandan daha iyi?

bunu da deneyebilirsiniz.

Nikolay Semko :
Deneyimli bir programcının bu gerçeğin farkında olması ve uygun olduğunda uygulaması yeterlidir.

O olması gereken bir şey değil, bunu bilmek zorunda.

Samimi olarak.

PS, formülünüz tüm değer kümesi için doğru değil.
y= ceil (x);  -> y=( int )(x+ 0.9999999999999997 );
Benimkini kontrol et, turu kısa bir formülle güncelledim, liste artık eksiksiz ve tamamen işlevsel, keyfini çıkarın.
 
Andrey Kisselyov :


PS, formülünüz tüm değer kümesi için doğru değil.

Benimkini kontrol et, turu kısa bir formülle güncelledim, liste artık eksiksiz ve tamamen işlevsel, keyfini çıkarın.

yukarıya bakın

x = 3 (herhangi bir tamsayı) olduğunda bir karışıklık vardır :))

Neden: