Вопрос

У меня есть метод, который занимается некоторыми географическими координатами в .NET, и у меня есть структура, которая хранит пару координат, так что если 256 передается для одного из координат, он становится 0. Однако в одном конкретном случае значение значения Приблизительно 255,9999998 рассматривается и, таким образом, хранится в структуре. Когда он напечатан в ToString (), он становится 256, что не должно произойти - 256 должно быть 0. Я не возражаю, если бы он напечатал 255.9999998, но тот факт, что он печатает 256, когда отладчик показывает 255,9999998, является проблемой. Наличие его хранилища и отображения 0 было бы еще лучше.

В частности, есть проблема с сравнением. 255.99999998 достаточно близко к 256, так что он должен равняться ему. Что мне делать при сравнении удвоений? Используйте какое -то значение Epsilon?


РЕДАКТИРОВАТЬ: В частности, моя проблема в том, что я беру ценность, выполняю некоторые расчеты, затем выполняю противоположные расчеты по этому числу, и мне нужно точно вернуть исходное значение.

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

Решение

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

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

Выше расчета, вероятно, суждено было быть 256, если вы не пробили арифметику без потерь, поскольку вы получите с рациональным типом.

Рациональные типы могут пойти по названию соотношения или дробик, и довольно просты для записи

Вот один примерАнкет Вот Другой


Редактировать....

Чтобы понять вашу проблему, убедитесь, что когда десятичное значение 0.01 преобразуется в двоичное представление, оно не может быть сохранено точно в конечной памяти. Шестиологичное представление для этого значения составляет 0,028F5C28F5C, где «28F5C» повторяется бесконечно. Таким образом, даже перед тем, как делать какие -либо расчеты, вы теряете точность, просто сохраняя 0,01 в бинарном формате.

Рациональные и десятичные классы используются для преодоления этой проблемы, хотя и с стоимостью производительности. Rational Tyms Избегайте этой проблемы, сохраняя числитель и знаменатель, чтобы представлять ваше значение. Десятичный тип Используйте двоичное закодированное десятичное десятичное формат, что может быть потеря в разделении, но может хранить общие десятичные значения точно.

Для вашей цели я все еще предлагаю рациональный тип.

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

Это звучит как проблема с тем, как напечатано число, а не о том, как оно хранится. А. double имеет около 15 важных цифр, поэтому он может сказать 255,9999998 из 256 с точностью.

Вы можете выбрать формат строки, которые должны позволять вам отображать столько, сколько вам нравится.

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

Вы должны решить себя по порогу, согласно которому два значения равны. Это означает использование так называемого Исправленные точки номера (в отличие от плавающей точкой). Тогда вы должны выполнить раунд вручную.

Я бы пошел с некоторым типом без знака с известным размером (например, uint32 или uint64, если они доступны, я не знаю .NET) и относиться к нему в виде мода 256 номеров фиксированной точки.

Например.

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

Или что-то более подробно, чтобы удовлетворить округление (к ближайшему, более низкому, более высоким, нечетным, даже). Самые высокие 8 бит фиксированного удерживают целочисленную часть, 24 нижних бита удерживают дробную часть. Абсолютная точность 2 ^ {- 24}.

Обратите внимание, что добавление и выгодность таких чисел естественным образом обертывает около 256. Для умножения вы должны остерегаться.

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