Вот интересный фрагмент спецификации C # из раздела 4.1.6:
Операции с плавающей точкой могут быть
выполняется с большей точностью, чем
тип результата операции. За
Например, некоторые аппаратные архитектуры
поддерживать «расширенный» или «длинный двойной»
тип с плавающей точкой с большим диапазоном
и точность, чем двойной тип,
и неявно выполнять все
операции с плавающей точкой с использованием этого
тип более высокой точности. Только в
может такая перегрузка в производительности
аппаратные архитектуры должны быть сделаны для
выполнять операции с плавающей точкой с
меньше точности, а не
требуют реализации, чтобы потерять
и производительность, и точность, C #
позволяет более высокую точность типа
используется для всех чисел с плавающей точкой
операции. Кроме доставки большего
точные результаты, это редко имеет какой-либо
измеримые эффекты.
Возможно, это один из "измеримых эффектов" благодаря тому призыву к Потолку. Взяв верхний предел числа с плавающей запятой, как отмечали другие, увеличивает разницу в 0,000000002 на девять порядков, потому что он превращает 15.99999999 в 16, а 16.00000001 в 17. Два числа, которые немного отличаются до операции, впоследствии значительно различаются; крошечная разница может быть объяснена тем фактом, что разные машины могут иметь более или менее «дополнительную точность» в своих операциях с плавающей запятой.
Некоторые связанные вопросы:
Чтобы решить вашу конкретную проблему, касающуюся вычисления соотношения сторон из числа с плавающей запятой: я бы, возможно, решил это совершенно другим способом. Я бы сделал такой стол:
struct Ratio
{
public int X { get; private set; }
public int Y { get; private set; }
public Ratio (int x, int y) : this()
{
this.X = x;
this.Y = y;
}
public double AsDouble() { return (double)X / (double)Y; }
}
Ratio[] commonRatios = {
new Ratio(16, 9),
new Ratio(4, 3),
// ... and so on, maybe the few hundred most common ratios here.
// since you are pinning results to be less than 20, there cannot possibly
// be more than a few hundred.
};
и теперь ваша реализация
public string AspectRatioAsString(double ratio)
{
var results = from commonRatio in commonRatios
select new {
Ratio = commonRatio,
Diff = Math.Abs(ratio - commonRatio.AsDouble())};
var smallestResult = results.Min(x=>x.Diff);
return String.Format("{0}:{1}", smallestResult.Ratio.X, smallestResult.Ratio.Y);
}
Обратите внимание, что код теперь выглядит очень похоже на операцию, которую вы пытаетесь выполнить: из этого списка общих соотношений выберите тот, в котором разница между данным соотношением и общим соотношением сведена к минимуму.