Преобразование мантиссы и экспоненты в двойную

В очень высокопроизводительном приложении мы Найти, что ЦП может вычислять длинные арифметические операции значительно быстрее, чем с двойными числами. Однако в нашей системе было определено, что нам никогда не нужно больше 9 десятичных знаков после запятой. Поэтому мы используем длинные числа для всей арифметики с плавающей запятой с понятной точностью 9 точек.

Однако в некоторых частях системы это более удобно из-за возможности чтения у работать с дублями.Таким образом, мы должны преобразовать длинное значение, предполагающее 9 десятичных знаков, в двойное.

Мы обнаруживаем, что простое взятие длинного числа и деление на 10 в степени 9 или умножение на 1, деленное на 10 в степени 9, дает неточное представление в двойном.

Чтобы решить эту проблему, мы использовали Math.Round (value, 9) , чтобы получить точные значения.

Однако Math.Round () ужасающе медленен для производительности.

Итак, наша идея на данный момент состоит в том, чтобы напрямую преобразовать мантиссу и экспоненту в двоичный формат числа с двойной точностью, поскольку - в этом случае не будет необходимости в округлении.

Мы узнали в Интернете, как исследовать биты двойного числа, чтобы получить мантиссу и показатель степени, но непонятно, как это изменить, чтобы взять мантиссу и показатель степени и изготовить двойное число, используя биты.

Есть предложения?

[Test]
public unsafe void ChangeBitsInDouble()
{
    var original = 1.0D;
    long bits;
    double* dptr = &original;
    //bits = *(long*) dptr;
    bits = BitConverter.DoubleToInt64Bits(original);
    var negative = (bits < 0);
    var exponent = (int) ((bits >> 52) & 0x7ffL);
    var mantissa = bits & 0xfffffffffffffL;
    if( exponent == 0)
    {
        exponent++;
    }
    else
    {
        mantissa = mantissa | (1L << 52);
    }
    exponent -= 1075;

    if( mantissa == 0)
    {
        return;
    }

    while ((mantissa & 1) == 0)
    {
        mantissa >>= 1;
        exponent++;
    }

    Console.WriteLine("Mantissa " + mantissa + ", exponent " + exponent);

}
8
задан ROMANIA_engineer 10 June 2016 в 08:33
поделиться