si parla che si deve testare quasi divisibilità con . La seguente teoria dovrebbe valere per i test quasi divisibilità contro potenze di due:
#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);
}
Quello che stiamo facendo è costringere il galleggiante, e galleggiante + SOGLIA a lungo.
f (long) f (long) (f + THRESHOLD)
63.9 63 64
64 64 64
64.1 64 64
Ora testiamo se (lungo) f è divisibile con 32. Basta controllare i cinque bit più bassi, se sono tutti a zero, il numero è divisibile per 32. Questo porta ad una serie di falsi positivi : 64.2 a 64.8, quando convertiti in long, sono anche 64 e passerebbero il primo test. Quindi, controlliamo se la differenza tra la loro forma troncata ef è minore o uguale a THRESHOLD.
Anche questo ha un problema: f - (float) l2 < = THRESHOLD è valido per 64 e 64.1, ma non per 63.9. Quindi, aggiungiamo un'eccezione per i numeri inferiori a 64 (che, quando incrementati di THRESHOLD e successivamente costretti a long - annotare che il test in discussione deve essere inclusivo con il primo test - è divisibile per 32), specificando che i 5 bit inferiori non sono zero. Ciò vale per 63 (1000000 - 1 == 1).
Una combinazione di questi tre test indica se il numero è divisibile per 32 o meno. Spero che questo sia chiaro, per favore perdona il mio strano inglese.
Ho appena testato l'estensibilità ad altre potenze di tre - il seguente programma visualizza numeri compresi tra 383,5 e 388,4 che sono divisibili per 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);
}
sembra funzionare bene finora!
+1 Questa è una soluzione molto ragionevole se non si dispone della funzione 'remainder' disponibile. –
o: else if (32.0f - offset
quinmars