11
votes

Comment obtenir les bits d'un "double" comme "long"

Je voudrais manipuler la représentation des nombres de points flottants dans C #. BarrinWriter et BinaryReader Faites-le de cette façon:

public virtual unsafe void Write(double value)
{
    ulong num = *((ulong*) &value);
    ...
}
public virtual unsafe double ReadDouble()
{
    ...
    ulong num3 = ...;
    return *((double*) &num3);
}


1 commentaires

Si vous êtes préoccupé par la vitesse, l'utilisation d'une approche syndicale est environ trois fois plus rapide comme appelant les API BitConverter dans mes tests rapides.


3 Réponses :


6
votes

Vous pouvez utiliser byte [] bitconverter.getbytes (double) et long bitconverter.toint64 (octet [], int) (Passant 0 comme étant l'index de démarrage) , mais à interne iirc Ces utilisent du code dangereux, plus ont les frais généraux d'un tableau. Choisissez votre poison ...


2 commentaires

Assez bon pour moi, je suppose. Je vois que le bitconverter a également une octet [] -> long convertisseur qui est probablement plus rapide que de combiner les octets manuellement.


Je pense que vous pouvez le faire sans appels d'API ni aucun code dangereux.



10
votes

Une autre solution consiste à utiliser une structure personnalisée avec une mise en page explicite qui définit à la fois un long et un double à offset 0. Cela équivaut à un Union < / code> dans C.

quelque chose comme ceci: xxx

puis utilisez ceci: xxx

Ceci évitera Tout code dangereux et devrait jouer assez vite aussi comme vous effectuez la conversion sur la pile.

Je n'ai pas essayé / compilé cela, mais je pense que cela devrait fonctionner :)

Modifier

Je viens d'essayer cela et ça marche. La valeur de longbytes ci-dessus est 4608236261112822104.

Certaines autres valeurs: xxx

Voici une méthode qui fait ce que vous voulez: xxx


9 commentaires

À bien des égards, les syndicats sont une forme de code dangereux, mais c'est une belle solution :)


Je ne pense pas qu'il n'y ait rien de plus dangereux ici. Au moins pas en fonction de la signification non vérifiable de dangereux en C #. Je pense que dangereux est un abus de .net vraiment.


@Drew - IIRC au moins un cadre (cf, SL ou MF) refuse de toucher les syndicats de leur nature.


(Ne me trompe pas; c'est une bonne réponse - et je serai de retour demain à +1; tout dehors aujourd'hui)


@Marc, je suis d'accord en principe sur les syndicats. Cependant, je trouve cette technique particulière dans le code source du framework .NET! J'ai certainement jamais manqué d'avoir un union mot-clé dans C #, mais il est bon de savoir que vous pouvez tirer cette astuce de résoudre des problèmes comme celui-ci lorsque vous avez besoin. En utilisant les syndicats en place du polymorphisme que le système de type fournit est lié à créer des données douteuses.


@Ajouter, oh je suis d'accord. En fait, j'ai essayé d'utiliser exactement cette approche pour éviter certains non sécurisé dans ma bibliothèque OSS pour animaux de compagnie; J'aimerais pouvoir me souvenir de quel cadre le rejetait et exactement comment. Probablement silverlight - SL est difficile.


@MARC, voulez-vous dire que le cadre introduit votre structure au moment de l'exécution et jeté une exception lors de la chargement? C'est fou. J'aimerais pouvoir me souvenir de la partie du cadre .NET, j'ai vu cette technique utilisée dans. Je pense que c'était probablement quelque part dans WPF ou WCF.


@Ajouter aurait été un numéro de compilateur ou de peverify. Peut-être que l'un d'entre eux omet simplement l'attribut de mise en page? Je ne me souviens pas hors de la main.


Mais un syndicat n'est certainement pas entièrement sûr; Il y a des choses bizarres que vous pouvez faire, surtout si vous ne faites pas délibérément que les choses se distinguent tout de suite;) Pas plus ou moins sûr que de faire la même chose via l'abus d'octets [].



6
votes

essayez-vous d'éviter tout le code dangereux tout à fait une alternative à ces méthodes spécifiques sur binarinreader et binarywriter ?

Vous pouvez utiliser bitconverter.doubleoint64bits et bitconverter.int64bittstodouble , qui sont conçus pour faire exactement ce dont vous avez besoin, bien que je pense qu'ils utilisent la même conversion dangereuse dans les scènes que le BinarinReader / Barronnage Méthodes .


1 commentaires

Bonne réponse! Je me demande comment j'ai manqué celui-là quand j'ai regardé Bitconverter. J'évite le code dangereux si possible pour que je puisse réutiliser le code par ex. Silverlight, mais j'aime utiliser le code vérifiable le plus rapide possible.