Вы упоминаете, что вы должны проверить почти делимость с 32 . Следующая теория должна быть верна для проверки почти делимости на степени два:
#define THRESHOLD 0.11
int nearly_divisible(float f) {
// printf(" %f\n", (a - (float)((long) a)));
register long l1, l2;
l1 = (long) (f + THRESHOLD);
l2 = (long) f;
return !(l1 & 31) && (l2 & 31 ? 1 : f - (float) l2 <= THRESHOLD);
}
То, что мы делаем, - это принуждаем поплавок, и плаваем + ПОРОГ в длинную позицию.
f (long) f (long) (f + THRESHOLD)
63.9 63 64
64 64 64
64.1 64 64
Теперь мы проверяем, делится ли (long) f на 32. Просто проверьте младшие пять битов, если все они установлены в ноль, число делится на 32. Это приводит к серии ложных срабатываний: от 64,2 до 64,8 , при преобразовании в long, тоже 64, и пройдет первый тест. Таким образом, мы проверяем, является ли разница между их усеченной формой и f меньше или равна THRESHOLD.
У этого тоже есть проблема: f - (float) l2 <= THRESHOLD будет верным для 64 и 64,1, но не для 63,9. Таким образом, мы добавляем исключение для чисел меньше 64 (которое при увеличении на THRESHOLD и последующем приведении к длинному - обратите внимание, что обсуждаемый тест должен включать в себя первый тест - делится на 32), указав, что младшие 5 битов не равны нулю. Это будет справедливо для 63 (1000000 - 1 == 1 <strong>11111 ).
Комбинация этих трех тестов будет указывать, делится ли число на 32 или нет. Я надеюсь, что это понятно, пожалуйста, прости мой странный английский.
Я только что проверил расширяемость на другие степени трех - следующая программа печатает числа между 383,5 и 388,4, которые делятся на 128.
#include <stdio.h>
#define THRESHOLD 0.11
int main(void) {
int nearly_divisible(float);
int i;
float f = 383.5;
for (i=0; i<50; i++) {
printf("%6.1f %s\n", f, (nearly_divisible(f) ? "true" : "false"));
f += 0.1;
}
return 0;
}
int nearly_divisible(float f) {
// printf(" %f\n", (a - (float)((long) a)));
register long l1, l2;
l1 = (long) (f + THRESHOLD);
l2 = (long) f;
return !(l1 & 127) && (l2 & 127 ? 1 : f - (float) l2 <= THRESHOLD);
}
Кажется, пока хорошо работает!