«Очистка» от неточностей двойных значений

1

У меня есть программа, которая получает данные стороннего API, но иногда двойные значения, которые я получил, представлены в "неточном" (или слишком точном) способе, например.

0,3 - 0,2999999999999

0,04 представлены как 0.03999999999999

Это вызывает проблемы, особенно когда я хотел бы проводить сравнения сравнений. Есть ли способ очистить "неточность" двойных ценностей по мере их получения?

О чем я могу думать:

    public Form1()
    {
        InitializeComponent();

        double x = 0.2999999999999; //from third party API          
        x = cleanDouble(x); //x=0.3
    }

    private double cleanDouble(double input)
    {
        string s = input.ToString("0.##########");
        double.TryParse(s, out input);
        return input;
    }

Есть ли более эффективный способ сделать это? Преобразование двойного в строку и обратно в двойное не кажется мне очень эффективным или элегантным.

Большое спасибо.

PS В целях моего применения точность значений, которые я получу, будет не более 0,00000001.

PPS Я не буду заранее знать, какую ценность я получу от стороннего API. Это может быть 0.0004999999999, 0.039999999999999, 100.049999999999999 и т.д.

PPPS Для этого вопроса мне нужно использовать double, а не decimal.

  • 1
    Вы никогда не сравниваете двойные числа на равенство Но сравните, достаточно ли они близки, чтобы ваше приложение в конкретном случае считалось равным.
  • 0
    Примечание: вы можете прочитать о том, как в компьютерах присутствуют значения типа double / float ... Например, нет 0,3 (в отличие от 0,25).
Теги:

3 ответа

1
Лучший ответ

Я точно не знаю, как вы собираетесь с подобными данными, так что это может или не может применяться, но можете ли вы быть в безопасности только Math.Round(double, int)? Это не совсем элегантно, это действительно больше, чем Band-Aid. Но если действительно нет способа очистить то, что вы втягиваете, это сработает.

Поскольку вы говорите, что не нужно превышать точность 0.00000001, вы можете просто сделать

Math.Round(value, 8);
  • 0
    Хаха, почему я не подумал об этом ... спасибо!
  • 0
    Иногда это просто берет другую пару глаз. :) Рад, что смог помочь!
2

Вы можете оставить номера в покое и написать свою собственную функцию сравнения. Что-то вроде:

Bool Test = IsRoughlyEqual(.0001, .0002, .01);

public bool IsRoughlyEqual(double NumA, double NumB, double Tolerance)
{
    double Result = Math.Abs(NumA - NumB);

    if (Result > Tolerance)
        return false;
    else
        return true;
}
  • 0
    +1 Это лучший ответ, чем мой на практике.
0

Это будет намного быстрее, чем преобразование double в строку, а затем перерассчитывание в double.

private double cleanDouble(double input)
{
    double ceil = Math.Ceil(input);
    if (ceil - input < 0.00000001)
        return ceil;

    double floor = Math.Floor(input);
    if (input - floor < 0.00000001)
        return floor;

    return input;
}

Имейте в виду, что некоторые цифры не могут быть на 100% точнее представлены двойным, поэтому необходим определенный допуск.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню