2013-11-20 14 views
8

754 toplam sipariş (IEEE 754), çift kesinlikli kayar noktalarında bir total order vardır (yani C++11 uygulamaları Linux gcc 4.8 gibi, IEEE-754 ilmiklere sahip bulunarak, ilgili/x86-64). double üzerinde ElbetteIEE <a href="http://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate" rel="noreferrer">IEEE floating point</a> wikipage göre standart C++ 11

, operator < sıklıkla toplam sipariş veren, ancak NaN istisnalar olduğu bilinen (iyi x != x test bir yolu x eğer double x; olarak ilan olduğu folklor bilinen bir NaN).

Sormamın sebebi, bir std::set<double> (aslında, JSON-benzeri bir Python benzeri değerler kümesi) ve setin bazı kanonik temsillere sahip olmasını isterim (pratik meselem, hem Linux'ta, hem de aynı sırayla sipariş edilen taşınabilir JSON -same verilerini yaymaktır)/x86-64 ve örneğin Linux/ARM'de, NaN gibi garip durumlarda bile.

Toplam siparişi almanın kolay bir yolunu bulamıyorum. Ben

// a totally ordering function, 
// return -1 for less-than, 0 for equal, +1 for greater 
int mydoublecompare(double x, double y) { 
    if (x==y) return 0; 
    else if (x<y) return -1; 
    else if (x>y) return 1; 
    int kx = std::fpclassify(x); 
    int ky = std::fpclassify(y); 
    if (kx == FP_INFINITE) return (x>0)?1:-1; 
    if (ky == FP_INFINITE) return (y>0)?-1:1; 
    if (kx == FP_NAN && ky == FP_NAN) return 0; 
    return (kx==ky)?0:(kx<ky)?-1:1; 
} 

kodlu Aslında, toplam sipariş (örneğin bit temelinde farklı NaN herkesin eşit olduğundan) (matematiksel olarak konuşma) bu gerçekten olmadığını biliyoruz, ama ben (aynı sahiptir umuyorum ya da çok yakın) birkaç ortak mimaride davranış.

Herhangi bir görüş veya öneriniz var mı?

(belki ben çok umurumda değil ve ben kasten umurumda değil yaklaşık signaling NaNs)

genel motivasyon JSON gösterimde olan tüm bellek durumunu devam bazı dinamik yazılan tercüman kodlama ediyorum yani, ve inatçı durumun mimarlar arasında kararlı olduğundan emin olmak istiyorum, başka bir deyişle JSON durumunu yükler ve döktüğümde, birçok mimaride (özellikle x86-64, ia-32, ARM 32 bit) idempotent kalır. ..).

+0

Toplam sipariş yerine "SWO" gerektirmez mi? –

+0

Üzgünüm, SWO ne anlama geliyor? Hızlı bir şekilde bulamıyorum! (bazı zayıf sıra)? –

+0

Sıkı zayıf sıra. –

cevap

6

Ben kullanırsınız: sürümünüzdeki if (x==y) return 0; sizin sürümü sadece bir ön sipariş olduğu anlamına onları eşit karşılaştırmak yapar oysa

int totalcompare(double x, double y) { 
    int64_t rx, ry; 

    memcpy(&rx, &x, sizeof rx); 
    memcpy(&ry, &y, sizeof ry); 

    if (rx == ry) return 0; 

    if (rx < 0) 
     rx = (~rx) | INT64_MIN; 
    if (ry < 0) 
     ry = (~ry) | INT64_MIN; 

    if (rx < ry) return -1; else return 1; 
} 

Bu, 0.0 ve -0.0 eşitsiz karşılaştırmak yapar. NaN değerleri geri kalanı üzerindedir ve farklı NaN'ler farklıdır. <= ile karşılaştırılabilir tüm değerler, yukarıdaki ilişki için aynı sırada olmalıdır.

Not: Yukarıdaki işlev C'dir. C++ bilmiyorum.

+0

Mimarlığa bağlı olmadığından emin misiniz? ('Int64_t' den farklı bir endianness 'çift olamaz mı?) –

+0

@BasileStarynkevitch Kayan noktalı değerler için tamsayı olanlardan farklı bir endensite ile temsil edilecek teoride mümkündür, ancak bunları temsil etmenin birçok avantajı vardır. aynı endensellik. Performans bilincine sahip herhangi bir tasarımcının doğal eğilimi, iki uçlu işlemcilerde bile her zaman aynı endianiteye sahip olmaktır. Herkesin sahip olduğu sıradan mimarilerle ilgili olarak, her iki modda da IA-32, x86-64 ve PowerPC için kefil olabilirim.ARM hakkında bilmiyorum. –

+0

Minor: 1) Bir int64_t, double' birliği daha zarif olmaz mıydı? 2) 'Memcpy (a, b, sz); ', sözde aynı boyutta kullanırken, memcpy (dest, src, sizeof * dest)' yi tercih ederim; sorun çıkarmak için. İyi bir çözüm için +1. – chux

İlgili konular