Странный результат при вычитании двойных чисел [дубликат]

StackOverflow https://stackoverflow.com/questions/2211378

  •  18-09-2019
  •  | 
  •  

Вопрос

Возможный дубликат:
Почему арифметика с плавающей запятой в C# неточна?

Я имел дело с некоторыми числами и C#, и следующая строка кода дает другое число, чем можно было бы ожидать:

double num = (3600.2 - 3600.0);

Я ожидал, что num будет 0,2, однако оказалось 0,19999999999998181.Есть ли причина, по которой он выдает близкую, но все же другую десятичную дробь?

Это было полезно?

Решение

Это потому что double представляет собой тип данных с плавающей запятой.

Если вам нужна более высокая точность, вы можете переключиться на использование decimal вместо.

Буквальный суффикс для decimal это м, поэтому использовать decimal арифметику (и вывести decimal результат) вы можете написать свой код как

var num = (3600.2m - 3600.0m);

Обратите внимание, что использование decimal.Это 128-битный тип данных, а не 64-битный, который имеет размер double.Это делает его более дорогим как с точки зрения памяти, так и с точки зрения обработки.Он также имеет гораздо меньший радиус действия, чем double.

Другие советы

Есть причина.

Причина в том, что способ хранения числа в памяти в случае типа данных double не позволяет точно представить число 3600,2.Это также не позволяет точно представить число 0,2.

0.2 имеет бесконечное представление в двоичном формате.Если Вы хотите сохранить его в памяти или регистрах процессора, чтобы выполнить какие-то вычисления, вместо него сохраняется какое-то число, близкое к 0,2 с конечным представлением.Это может быть неочевидно, если вы запустите такой код.

double num = (0.2 - 0.0);

Это связано с тем, что в этом случае все двоичные цифры, доступные для представления чисел в типе данных double, используются для представления дробной части числа (есть только дробная часть), и точность выше.Если вы храните число 3600,2 в объекте типа double, некоторые цифры используются для представления целой части - 3600, а меньше цифр представляют дробную часть.Точность ниже, а дробная часть, которая фактически хранится в памяти, настолько отличается от 0,2, что это становится очевидным после преобразования из double в строку.

Измените свой тип на decimal:

decimal num = (3600.2m - 3600.0m);

Вам также следует прочитать этот.

Видеть Википедия

Не могу объяснить это лучше.Я также могу предложить прочитать Что должен знать каждый ученый-компьютерщик об арифметике с плавающей запятой.Или посмотрите похожие вопросы на Переполнение стека.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top