В очень высокопроизводительном приложении мы Найти, что ЦП может вычислять длинные арифметические операции значительно быстрее, чем с двойными числами. Однако в нашей системе было определено, что нам никогда не нужно больше 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);
}