2010-08-25 16 views
14

J'ai cette valeur:Convertir en deux hex en C#

double headingAngle = 135.34375; 

Je voudrais le convertir en HEX et imprimer le HEX à la console. J'ai déjà converti une chaîne et int dans leurs valeurs HEX respectives, mais un double semble être beaucoup plus difficile. Quelqu'un peut me diriger dans la bonne direction?

+1

L'une des raisons pour lesquelles il n'existe pas de fonction prête à l'emploi est que cela est totalement inutile. Qui peut (et veut) lire un double comme hex? –

+0

d'accord avec Henk. @rross: Je meurs d'envie de savoir, pourquoi avez-vous besoin de faire cela? – tenfour

+2

@Henk Il n'y a rien d'intrinsèquement moins utile de représenter une valeur non-entière en hexadécimal qu'en décimal ou toute autre base. Nous sommes juste plus habitués à la décimale. –

Répondre

12

Eh bien, je googlé pendant une minute ou deux et selon this ici est une solution tout à fait ellegant

double d = 12.09; 
    Console.WriteLine("Double value: " + d.ToString()); 
    byte[] bytes = BitConverter.GetBytes(d); 
    Console.WriteLine("Byte array value:"); 
    Console.WriteLine(BitConverter.ToString(bytes)); 
+5

Je sais que cette question est assez ancienne, mais il vaut probablement la peine de souligner que ce code ne convertira pas la valeur du double en sa représentation hexadécimale. Au contraire, il va écrire la représentation hexadécimale des bits qui sont utilisés pour stocker le nombre en interne. Pour un nombre à virgule flottante, les deux sont des choses différentes! –

+1

Point pris. Bien que je n'aie entendu parler d'aucune norme de notation hexadécimale pour la représentation des valeurs à virgule flottante. Bien sûr, il est important de se souvenir de la spécification du matériel et de tous les trucs big/low endian. Cependant, la norme IEEE 754 est très populaire et largement utilisée. Alors.. – Bart

4

Vous pouvez convertir la base 10 en base 16 en multipliant continuellement la fraction par 16, en supprimant le nombre entier et en répétant avec le reste.

Donc, pour convertir 0,1 à Hex Décimal

0.1 * 16 
= 1.6 

So 1 devient la première valeur hexadécimale. Continuez avec les 0.6 restants

0.6 * 16 = 9.6 

Alors 9 devient la deuxième valeur hexadécimale. Garder aller avec le reste 0,6

0.6 * 16 = 9.6 

etc.

donc 0.1 décimal = 0.19999 .. hex récurrente

De mémoire cela fonctionne pour tout radix. Il est évident que dans l'hexagone une valeur entière de 10 serait une etc.

3

En supposant que vous voulez convertir à la base/radix hexadécimal, ce qui suit devrait faire l'affaire:

static void Main(string[] args) 
{ 
    Console.WriteLine(Base16(135.34375, 10)); 
    Console.ReadLine(); 
} 

private static string Base16(double number, int fractionalDigits) 
{ 
    return Base(number, fractionalDigits, new char[]{ 
     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
     'A', 'B', 'C', 'D', 'E', 'F' }); 
} 

private static string Base(double number, int fractionalDigits, params char[] characters) 
{ 
    int radix = characters.Length; 
    StringBuilder sb = new StringBuilder(); 

    // The 'whole' part of the number. 
    long whole = (long)Math.Floor(number); 
    while (whole > 1) 
    { 
     sb.Insert(0, characters[whole % radix]); 
     whole = whole/radix; 
    } 

    // The fractional part of the number. 
    double remainder = number % 1; 
    if (remainder > Double.Epsilon || remainder < -Double.Epsilon) 
    { 
     sb.Append('.'); 

     double nv; 
     for (int i = 0; i < fractionalDigits; i++) 
     { 
      nv = remainder * radix; 
      if (remainder < Double.Epsilon && remainder > -Double.Epsilon) 
       break; 
      sb.Append(characters[(int)Math.Floor(nv)]); 
      remainder = nv % 1; 
     } 
    } 

    return sb.ToString(); 
} 

La conversion hexadécimal de 135,34375 est 87.58.

0

Essayez ceci:

public static string Format(double number, double @base) 
{ 
    StringBuilder format = new StringBuilder(); 
    if(number < 0) 
    { 
     format.Append('-'); 
     number = -number; 
    } 
    double log = Math.Log(number, @base); 
    bool frac = false; 
    double order; 
    if(log < 0) 
    { 
     frac = true; 
     format.Append(digits[0]); 
     format.Append('.'); 
     order = 1/@base; 
    }else{ 
     order = Math.Pow(@base, Math.Floor(log)); 
    } 
    while(number != 0 || order >= 1) 
    { 
     double digit = Math.Floor(number/order); 
     if(digit >= @base) break; 
     number = number-digit*order; 
     number = Math.Round(number, 15); 
     if(order < 1 && !frac) 
     { 
      format.Append('.'); 
      frac = true; 
     } 
     order /= @base; 
     if(digit >= 10) 
     { 
      format.Append((char)('A'+(digit-10))); 
     }else{ 
      format.Append((char)('0'+digit)); 
     } 
    } 
    return format.ToString(); 
} 

Utilisez comme Format(headingAngle, 16). Vous pouvez également commenter number = Math.Round(number, 15); pour des résultats plus intéressants. Result

Le résultat est au format culture invariante. Pour 135.34375, il renvoie 87.58.