Является ли двойное умножение разбитым в .NET?

Если в C # выполняется следующее выражение:

double i = 10*0.69; 

i : 6.8999999999999995 . Зачем?

Я понимаю, что число, такое как 1/3, может быть трудно представлять в двоичном формате, так как оно имеет бесконечные повторяющиеся десятичные разряды, но это не относится к 0,69. А 0,69 легко может быть представлен в двоичном, одном двоичном числе для 69, а другой – в позиции десятичного разряда.

Как мне обойти это? Использовать decimal тип?

Потому что вы неправильно поняли арифметику с плавающей запятой и как хранятся данные.

Фактически, ваш код на самом деле не выполняет какую-либо арифметику во время выполнения в этом конкретном случае – компилятор выполнит ее, а затем сохранит константу в сгенерированном исполняемом файле. Тем не менее, он не может хранить точное значение 6.9, потому что это значение не может быть точно представлено в формате с плавающей точкой, так же как 1/3 не может быть точно сохранено в конечном десятичном представлении.

Посмотрите, помогает ли эта статья .

почему frameworks не работают вокруг этого и скрывают эту проблему от меня и дают мне правильный ответ, 0.69 !!!

Прекратите вести себя, как менеджер дильберт, и согласитесь, что компьютеры, хотя и classные и удивительные, имеют ограничения. В вашем конкретном случае это не просто «спрятать» проблему, потому что вы специально сказали ей это не делать. Язык (компьютер) предоставляет альтернативы формату, который вы не выбрали. Вы выбрали double, который имеет определенные преимущества перед десятичным и некоторые недостатки. Теперь, зная ответ, вы расстроены тем, что недостатки не волшебным образом исчезают.

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

Так будет каждый другой метод хранения чисел, так как у нас нет бесконечных бит. Наша работа в качестве программистов – работать с ограниченными ресурсами, чтобы сделать крутые вещи. Они добрались до вас на 90%, просто доставьте факел домой.

А 0,69 легко может быть представлен в двоичном, одном двоичном числе для 69, а другой – в позиции десятичного разряда.

Я думаю, что это распространенная ошибка – вы думаете о числах с плавающей запятой, как если бы они были базовыми 10 (т.е. десятичными – следовательно, моим акцентом).

Итак, вы думаете, что в этот двойник есть две части из целого числа: 69 и разделите на 100, чтобы перейти на десятичное место для перемещения, что также может быть выражено как:
69 x 10 до мощности -2 .

Однако поплавки сохраняют «положение точки» в качестве базы-2 .

Ваш поплавок фактически хранится как:
68999999999999995 x 2 к мощности некоторого большого отрицательного числа

Это не так много, как только вы привыкли к этому – большинство людей знают и ожидают, что 1/3 не может быть точно выражена как десятичная или процентная. Просто фракции, которые не могут быть выражены в базе-2, различны.

но почему frameworks не работают вокруг этого и скрывают эту проблему от меня и дают мне правильный ответ, 0.69 !!!

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

Более эффективное решение состоит в том, чтобы не выводить полное значение представления и явно указывать точность, необходимую для вашего вывода. Если вы отформатируете вывод до двух знаков после запятой, вы увидите ожидаемый результат. Однако, если это финансовое приложение десятичное – это именно то, что вы должны использовать – вы видели Superman III (и Office Space), не так ли?)

Заметим, что все они являются конечной аппроксимацией бесконечного диапазона, а просто десятичной и двойной используют другой набор приближений. Преимущество десятичного числа – это то же самое приближение, которое вы делали бы, если бы выполняли расчет самостоятельно. Например, если вы рассчитали 1/3, вы в конечном итоге прекратите писать 3, когда это будет «достаточно хорошо».

По той же причине, что 1/3 в десятичных системах получается как 0,3333333333333333333333333333, а не точная доля, которая бесконечно длинная.

Чтобы обойти это (например, для отображения на экране), попробуйте следующее:

 double i = (double) Decimal.Multiply(10, (Decimal) 0.69); 

Кажется, каждый ответил на ваш первый вопрос, но проигнорировал вторую часть.

  • Создание математической библиотеки с использованием Generics в C #
  • Обратный комплексный 2D-справочный стол
  • Лучший способ найти все факторы заданного числа
  • Неопределенная ссылка на `sin`
  • Объясните этот fragment, который находит максимум два целых числа без использования if-else или любого другого оператора сравнения?
  • Использование матрицы для поочередного поворота прямоугольников
  • Какова наилучшая практика для округления поплавка до 2 десятичных знаков?
  • Существует ли в Java обычная библиотека рациональных чисел?
  • c ++ Sin and Cos
  • Самый быстрый способ определить, существует ли целое число между двумя целыми числами (включительно) с известными наборами значений
  • Написание собственной функции квадратного корня
  • Давайте будем гением компьютера.