Округление последней цифры меняется после обновления Windows .NET

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

Это изменение можно увидеть уже при отладке в Visual Studio и наведении на переменную. Позже значение записывается в выходной файл и также изменяется в нем (без запуска отладчика).

Минимальный воспроизводимый пример

var output = -0.07765290852439255;
Trace.WriteLine(output); // This printout changes with the update.

var dictionary = new Dictionary<int, double>();
dictionary[0] = output; // Hover over dictionary to see the change in debug mode

Фон

Расчетное значение исходит из

output[date] = input[date] / input[previousDate] - 1;

Не обращая внимания на потерю точности в арифметике с плавающей точкой, я могу выполнить вычисление в окне Immediate и получить -0.07765290852439255 как до, так и после обновления.

Однако при наведении output переменная, я вижу
{[2011-01-12 00:00:00, -0.0776529085243926]} до обновления и
{[2011-01-12 00:00:00, -0.0776529085243925]} после, и эта разница также распространяется в выходной файл.

Кажется, что вычисленное значение одинаково до и после обновления, но его представление округляется по-разному.

Входные значения

{[2011-01-11 00:00:00, 0.983561000400506]} 
{[2011-01-12 00:00:00, 0.907184628008246]}

Целевая структура установлена ​​на .NET Framework 4.6.1

Вопрос

Что я могу сделать, чтобы получить предыдущее поведение при сохранении обновлений?

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

KB4486153 - это обновление для Microsoft .NET Framework 4.8, см. https://support.microsoft.com/en-us/help/4486153/microsoft-net-framework-4-8-on-windows-10-version-1709-windows-10-vers

1 ответ

ОП сталкивается с одной из распространенных проблем математики с плавающей точкой. С новым программным обеспечением нужно ли последовательные ответы или лучший ответ? (Обновление лучше)


Некоторая информация, чтобы помочь продвинуть проблему.

var output = -0.07765290852439255;

С общей двоичной 64-кодовой кодировкой1, из-за двоичной природы двоичной 64, output принимает точное значение

-0.077652908524392 54987160666132695041596889495849609375

Ниже показаны предыдущие и следующие возможные double тоже как шестнадцатеричный и десятичный FP.

                      -0.077652908524392 5
-0x1.3e10f9e8d3217p-4 -0.077652908524392 53599381885351249366067349910736083984375
-0x1.3e10f9e8d3218p-4 -0.077652908524392 54987160666132695041596889495849609375
                      -0.077652908524392 55
-0x1.3e10f9e8d3219p-4 -0.077652908524392 56374939446914140717126429080963134765625
                      -0.077652908524392 6

Лучшее округленное до ближайшего значения -0.077652908524392 55 (который закодирован в точности как -0.077652908524392 5498...) на одну меньшую цифру то -0.077652908524392 5, После обновления код печатает лучший ответ - по крайней мере, в этом единственном случае.

Я не рассматриваю это как изменение округления так же, как улучшенное преобразование в текст.

Что я могу сделать, чтобы получить предыдущее поведение при сохранении обновлений?

Возможно, все же похоже, что обновление представляет лучший результат.

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

Используйте шестнадцатеричный вывод с плавающей запятой (как с "%a" в C) один из подходов к получению не изменяет представление, но не десятичный вывод незнаком.


1 При других кодировках точное значение могло быть ближе к -0.077652908524392 6 чем -0.077652908524392 5,

Другие вопросы по тегам