Фон
Рассмотрим проверку трех двойников low
, width
и high
так, чтобы выполнялись следующие три правила:
low < high
;width > 0
; иwidth
вписывается в(high - low)
"точно" целое число раз.
По сути, три значения должны указывать диапазон, который должен быть разделен на определенное количество интервалов, каждый из которых имеет «точно» одинаковую ширину, при этом ни одна часть диапазона не может быть неучтенной.
Например:
(A) low = -0.5
, width = 0.005
и high = 0.5
будет указывать диапазон с действительной шириной ячейки, поскольку можно создать «ровно» 200 полных ячеек, тогда как
(B) low = -0.5
, width = 0.275
и high = 0.5
будет указывать диапазон с недопустимой шириной ячейки, так как можно создать 3 полных ячейки, но часть диапазона не покрывается этими ячейками.
Проблема
Как лучше всего подойти к третьему правилу проверки, учитывая природу двойных чисел с плавающей запятой?
Моя первая наивная попытка состояла из:
fmod( high - low, width ) == 0.0
но, к сожалению, fmod возвращает 0,005, например (A) - мой отладчик говорит мне, что двойное значение 0,005 фактически содержит значение 0.0050000000000000001
.
Должен ли я придумывать свое собственное решение, чтобы включить допуски, или есть более элегантное решение этой проблемы?
Это то, что у меня есть на данный момент:
bool valid(double range, double width, double tolerance = 0.000000001)
{
assert(width > 0 && range > 0);
while( range > 0 && range > tolerance )
{
range -= width;
}
return abs(range) <= tolerance;
}
Обратите внимание на полную и абсолютную произвольность значения допуска по умолчанию...