NaN boksun amacı nedir?


44

21. Yüzyıl C'yi okumak Ben "NaNs ile Olağanüstü Sayısal Değerleri İşaretlemek" bölümündeki 6. bölüme geldim ; burada bazı rasgele bit modellerini depolamak, işaretçiler veya işaretçiler olarak kullanmak için mantisan bitlerinin kullanımını açıklıyor (kitaptan bahsediyor) Bu WebKit bu tekniği kullanır).

Bu tekniğin faydasını anladığımdan emin değilim, bir hack olarak görüyorum (bir NaN'deki mantisanın değerini önemsemeyen donanıma güveniyor) ama Java geçmişinden gelmiyorum C. pürüzlülüğü

İşte bir NaN'de bir işaretleyiciyi ayarlayan ve okuyan kod pasajı

#include <stdio.h>
#include <math.h> //isnan

double ref;

double set_na(){
    if (!ref) {
        ref=0/0.;
        char *cr = (char *)(&ref);
        cr[2]='a';
    }
    return ref;
}

int is_na(double in){
    if (!ref) return 0;  //set_na was never called==>no NAs yet.

    char *cc = (char *)(&in);
    char *cr = (char *)(&ref);
    for (int i=0; i< sizeof(double); i++)
        if (cc[i] != cr[i]) return 0;
    return 1;
}

int main(){
    double x = set_na();
    double y = x;
    printf("Is x=set_na() NA? %i\n", is_na(x));
    printf("Is x=set_na() NAN? %i\n", isnan(x));
    printf("Is y=x NA? %i\n", is_na(y));
    printf("Is 0/0 NA? %i\n", is_na(0/0.));
    printf("Is 8 NA? %i\n", is_na(8));
}

yazdırır:

Is x=set_na() NA? 1
Is x=set_na() NAN? 1
Is y=x NA? 1
Is 0/0 NA? 0
Is 8 NA? 0

ve JSValue.h webkit'te kodlamayı açıklar, fakat neden kullanıldığını değil.

Bu tekniğin amacı nedir? Alanın / performansın faydaları, çılgınca doğasını dengelemek için yeterince yüksek mü?


basit bir örnek verebilir misiniz?
BЈовић

Açıkçası , OP'nin NaN'lerin nerelerde kullanılabileceğini sorduğu sorusu
cırcır böceği

1
@ ratchetfreak, bunu düşündüren ne?
Winston Ewert,

@ratchetfreak: Soru, NaN'in sinyaliyle ilgili değil, JSValue.h webkitinin açıkladığı gibi, Ama yeni bir şey keşfetmeme izin verdiğiniz için teşekkür ederiz!
andijcr

1
@Hudson isnan () si, anadaki ikinci baskıda kullanılır. İs_an () işlevinin amacı, giriş çiftinin bit deseninin ref global değişkeninde kaydedilene eşit olup olmadığını test etmektir.
andijcr

Yanıtlar:


63

Dinamik olarak yazılmış bir dil uygularken, nesnelerinizden herhangi birini tutabilecek tek bir türün olması gerekir. Bunun için farkında olduğum üç farklı yaklaşım var:

İlk olarak, işaretçilerin etrafından dolaşabilirsiniz. CPython uygulamasının yaptığı şey budur. Her nesne bir PyObjectişaretçidir. Bu işaretçiler çevrilir ve PyObject yapısındaki ayrıntılara bakarak türü tespit ederek işlemler gerçekleştirilir.

Dezavantajı, sayı gibi küçük değerlerin kutulu değerler olarak depolanmasıdır, Yani küçük 5'iniz bir yerlerde bir bellek bloğu olarak depolanır. Bu da bizi Lua tarafından kullanılan sendika yaklaşımına götürüyor. A yerine PyObject*, her bir değer, türü belirtmek için bir alan ve daha sonra desteklenen tüm farklı türlerin birleşiminden oluşan bir yapıdır. Bu şekilde, küçük değerlere herhangi bir bellek ayırmaktan kaçınırız, bunun yerine onları doğrudan birliğe depolarız.

NaNYaklaşım depolar çiftlerde olarak her şey ve kullanılmayan kısmını yeniden kullanır NaNekstra depolama için. Sendika yöntemine göre avantaj, tür alanını korumamızdır. Geçerli bir çift ise, iki katıdır, aksi takdirde mantis gerçek nesnenin bir göstergesidir.

Unutma, bu her javascript nesnesidir. Her değişken, bir nesnedeki her değer, her ifade. Bunların hepsini 96 bit'ten 64 bit'e düşürebilirsek bu oldukça etkileyicidir.

Kesmeye değer mi? Etkin Javascript için çok fazla talep olduğunu hatırlayın. Javascript, birçok web uygulamasındaki tıkanıklıktır ve bu nedenle daha hızlı hale getirmek yüksek önceliklidir. Performansla ilgili nedenlerden dolayı belirli derecede bir kesinlik getirmek makul. Çoğu durumda, bu kötü bir fikir olurdu, çünkü çok az kazanç için bir karmaşıklık derecesi getiriyor. Ancak bu özel durumda, bellek ve hız iyileştirmeleri için faydalı olacaktır.


2
Aslında CPython küçük sayıları önbelleğe alır. Bkz. Hg.python.org/cpython/file/e6cc582cafce/Objects/longobject.c
Phillip Cloud

1
@cpcloud, true, ancak bu ayrıntı uygun görünmüyordu.
Winston Ewert,

1
@WinstonEwert Haklısın. Yazdıklarını okuduktan sonra da aynı şeyi düşündüm.
Phillip Cloud,

2
Tüm değerlerin "boks edilmesini" önlemek için ilkel tipte bitlerin kullanılması, zaman kazanmış bir tekniktir. Smalltalk onu 1970'lerde kullandı, ya bir nesneyi ya da 15 bit'i işaret etmek için 16 bit tam sayılardan bir biti çaldı SmallInteger.
Jonathan Eunice

2
@JonathanEunice, gerçekten mi? Bu sadece beni şaşırtıyor çünkü 16 bitte uzunca bir süredir vazgeçmeye razıyım.
Winston Ewert

7

"İstisnai değerler" için NaN kullanılması, fazladan bir boole değişkenine ihtiyaç duyulmaması için iyi bilinen ve bazen yararlı bir tekniktir this_value_is_invalid. Akıllıca kullanılırsa, herhangi bir performans değişikliği olmadan kodunu daha kısa, daha temiz, daha basit ve daha iyi okunabilir hale getirmeye yardımcı olabilir.

Elbette bu tekniğin bazı tuzakları vardır (bkz. Http://ppkwok.blogspot.co.uk/2012/11/java-cafe-1-never-write-nan-nan_24.html ), fakat Java gibi dillerde veya çok benzer C #) Float.isNaNNaN'lerle uğraşmayı kolaylaştırmak gibi standart kütüphane fonksiyonları vardır . Tabii ki, Java'da alternatif olarak Floatve Doublesınıfını ve C # 'da null değerlerini kullanabilirsiniz float?ve double?size nullgeçersiz kayan nokta sayıları için NaN yerine kullanma imkanı sunar , ancak bu teknikler performans ve hafıza üzerinde önemli olumsuz etkiye sahip olabilir. programınızın kullanımı.

C'de NaN kullanımı% 100 taşınabilir değildir, bu doğrudur, ancak IEEE 754 kayan nokta standardının bulunduğu her yerde kullanabilirsiniz. AFAIK bu günümüzde neredeyse her ana donanımdır (veya en azından çoğu derleyicinin çalışma ortamı bunu desteklemektedir). Örneğin, bu SO yayını , C'deki NaN kullanımı hakkında daha fazla bilgi edinmek için bazı bilgiler içerir.


Java'da otomatik boks dağınık ve kaçınılması gereken, sadece boş bir değer sağlamak için kullanmak gülünç ve hatalara eğilimli
cırcır ucube

web setinin NaN-boxing'i kullandığı yere bağlantı sorusunu düzenledim. Webkit sinyali 'NaN' dışındaki NaN daha geniş bir kullanımı vardır görünüyor
andijcr

2
@ ratchetfreak: Tabii ki bu benim amacımı destekliyor
Doc Brown
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.