Во время регрессионного тестирования мы заметили, что неявные расширяющие преобразования происходят в другом порядке, что приводит к некоторым ошибкам. результаты меняются.
Похоже, что в .NET Framework операция типа: d1= f1 * f2 сначала преобразует f1 > и f2 удваиваются перед выполнением умножения, тогда как в .NET 8 сначала будет выполняться умножение между числами с плавающей запятой, а затем произойдет расширение.
Я знаю об этом поведение двоичных вычислений с плавающей запятой. Я не пытаюсь утверждать, что один из них «неправильный», а просто пытаюсь понять, почему поведение было изменено.
И: Есть ли какой-нибудь способ временно изменить поведение .NET 8 обратно на поведение .NET Framework, чтобы мы могли лучше понять наш регрессионный тест?
(P.S. да, я знаю, что это не было бы проблемой, если бы у нас вообще не было неявных преобразований. Но это большая устаревшая кодовая база, и я не могу ее легко изменить.)
Код тестирования консольного приложения. :
Код: Выделить всё
Console.WriteLine(".NET 8");
Console.WriteLine("Input Float: 0.3333333F");
float f1 = 0.3333333F;
Console.WriteLine("Decimal: " + f1.ToString());
Console.WriteLine("Binary: " + GetFloatBinary(f1));
Console.WriteLine();
Console.WriteLine("Float multiplication first, then conversion");
Console.WriteLine("f2 = f1 * f1");
float f2 = f1 * f1;
Console.WriteLine("Decimal: " + f2.ToString());
Console.WriteLine("Binary: " + GetFloatBinary(f2));
Console.WriteLine("d1 = (double)f2");
double d1 = (double)f2;
Console.WriteLine("Decimal: " + d1.ToString());
Console.WriteLine("Binary: " + GetDoubleBinary(d1));
Console.WriteLine();
Console.WriteLine("Conversion first, multiplication second");
Console.WriteLine("d2 = (double)f1 * (double)f1");
double d2 = (double)f1 * (double)f1;
Console.WriteLine("Decimal: " + d2.ToString());
Console.WriteLine("Binary: " + GetDoubleBinary(d2));
Console.WriteLine();
Console.WriteLine("Let the platform decide");
Console.WriteLine("d3 = f1 * f1");
double d3 = f1 * f1;
Console.WriteLine("Decimal: " + d3.ToString());
Console.WriteLine("Binary: " + GetDoubleBinary(d3));
Console.WriteLine();
Console.ReadLine();
static string GetFloatBinary(float value)
{
const int bitCount = sizeof(float) * 8;
int intValue = System.BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
return Convert.ToString(intValue, 2).PadLeft(bitCount, '0');
}
static string GetDoubleBinary(double value)
{
const int bitCount = sizeof(double) * 8;
int intValue = System.BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
return Convert.ToString(intValue, 2).PadLeft(bitCount, '0');
}
Код: Выделить всё
.NET FRAMEWORK
Input Float: 0.3333333F
Decimal: 0.3333333
Binary: 00111110101010101010101010101010
Float multiplication first, then conversion
f2 = f1 * f1
Decimal: 0.1111111
Binary: 00111101111000111000111000110111
d1 = (double)f2
Decimal: 0.111111097037792
Binary: 0000000000000000000000000000000011100000000000000000000000000000
Conversion first, multiplication second
d2 = (double)f1 * (double)f1
Decimal: 0.111111097865635
Binary: 0000000000000000000000000000000011100011100011100011100100000000
Let the platform decide
d3 = f1 * f1
Decimal: 0.111111097865635
Binary: 0000000000000000000000000000000011100011100011100011100100000000
Код: Выделить всё
.NET 8
Input Float: 0.3333333F
Decimal: 0.3333333
Binary: 00111110101010101010101010101010
Float multiplication first, then conversion
f2 = f1 * f1
Decimal: 0.1111111
Binary: 00111101111000111000111000110111
d1 = (double)f2
Decimal: 0.1111110970377922
Binary: 0000000000000000000000000000000011100000000000000000000000000000
Conversion first, multiplication second
d2 = (double)f1 * (double)f1
Decimal: 0.11111109786563489
Binary: 0000000000000000000000000000000011100011100011100011100100000000
Let the platform decide
d3 = f1 * f1
Decimal: 0.1111110970377922
Binary: 0000000000000000000000000000000011100000000000000000000000000000
Спасибо за понимание!
Подробнее здесь: https://stackoverflow.com/questions/789 ... s-from-net