Как преобразовать десятичные дроби в шестнадцатеричные дроби?

Итак, я думал, как вы преобразовываете десятичную дробь в шестнадцатеричную дробь? Какие методы конвертирования и короткие сокращения?

Ответ 1

Вы можете использовать этот алгоритм:

  • Возьмите дробную часть числа (т.е. целочисленная часть равна нулю)
  • Умножить на 16
  • Преобразовать целочисленную часть в шестнадцатеричную и поместить ее
  • Перейдите к шагу 1

Например, давайте выясним шестнадцатеричное представление для pi = 3.141592653589793...

целочисленная часть очевидна - 0x3; так как для дробной части (0,141592653589793) мы имеем

  0.14159265358979 * 16 =  2.26548245743664; int part  2 (0x2); frac 0.26548245743664
  0.26548245743664 * 16 =  4.24771931898624; int part  4 (0x4); frac 0.24771931898624
  0.24771931898624 * 16 =  3.96350910377984; int part  3 (0x3); frac 0.96350910377984
  0.96350910377984 * 16 = 15.41614566047744; int part 15 (0xF); frac 0.41614566047744
  0.41614566047744 * 16 =  6.65833056763904; int part  6 (0x6); frac 0.65833056763904
  0.65833056763904 * 16 = 10.53328908222464; int part 10 (0xA); ...

So pi (шестнадцатеричный) = 3.243F6A...

Возможная (С#) реализация

public static String ToHex(Double value) {
  StringBuilder Sb = new StringBuilder();

  if (value < 0) {
    Sb.Append('-');

    value = -value;
  }

  // I'm sure you know how to convert decimal integer to its hexadecimal representation
  BigInteger bi = (BigInteger) value;
  Sb.Append(bi.ToString("X"));

  value = value - (Double)bi;

  // We have integer value in fact (e.g. 5.0)
  if (value == 0)
    return Sb.ToString();

  Sb.Append('.');

  // Double is 8 byte and so has at most 16 hexadecimal values
  for (int i = 0; i < 16; ++i) {
    value = value * 16;
    int digit = (int) value;

    Sb.Append(digit.ToString("X"));

    value = value - digit;

    if (value == 0)
      break;
  }

  return Sb.ToString();
}

Тест

   Console.Write(ToHex(Math.PI)); // <- returns "3.243F6A8885A3"

Ответ 2

Вы можете получить дробную часть, умножив входной номер на целое число шестнадцатеричных цифр. Затем вы можете использовать регулярное целочисленное преобразование. Например, чтобы получить 6 символов после (шестнадцатеричной) десятичной точки, умножьте дробную часть на 0x1000000.

Вот какой код Java это сделает.

String toHexFraction(double x, int digits) {
    // Get fractional part.
    if (x < 0.0)
        x = 0.0 - x;
    x = x % 1.0;

    // Shift left by n digits
    long multiplier = (1L << (digits * 4));
    long fraction = (long)(x * multiplier);

    // Convert integer to hex string.
    // String should have at least n digits; prefix with zeros if not.
    String hex = Long.toHexString(fraction);
    String padding = "000000000000000";
    hex = padding.substring(0, digits - hex.length()) + hex;

    return hex;
}

String toHexInteger(double x) {
    long whole = (long) x;
    String prefix;
    if (whole < 0) {
        // Long.toHexString treats the number as an unsigned integer.
        whole = 0 - whole;
        prefix = "-";
    } else {
        prefix = "";
    }
    return Long.toHexString(whole);
}

String toHex (double x, int digits) {
    return toHexInteger(x) + "." + toHexFraction(x, digits);
}

Число цифр будет ограничено наибольшим целым числом, которое вы можете представить в двойном.

Это должно работать и для других квадратных оснований, например. для восьмеричного изменения digits * 4 до digits * 3 и используйте Long.toOctalString.