Skip to content

Instantly share code, notes, and snippets.

@dockimbel
Created February 16, 2025 21:15
Show Gist options
  • Save dockimbel/e479ad63adcacb690dd80c8ebec10de9 to your computer and use it in GitHub Desktop.
Save dockimbel/e479ad63adcacb690dd80c8ebec10de9 to your computer and use it in GitHub Desktop.
C function for comparing float values that are close enough (<= 10 ULP)
// generated from https://chatgpt.com/canvas/shared/67afab561d4c8191bbb497e5cef5147b
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#define ULP_TOLERANCE 10
int float_almost_equal(float a, float b) {
// Handle NaN cases
if (isnan(a) || isnan(b)) return 0;
// Handle exact equality
if (a == b) return 1;
// Handle large numbers as almost equal to infinity using bit manipulation
int32_t ai = *(int32_t*)&a;
int32_t bi = *(int32_t*)&b;
int32_t abs_ai = ai & 0x7FFFFFFF;
int32_t abs_bi = bi & 0x7FFFFFFF;
int32_t float_max_bits = 0x7F7FFFFF; // Largest finite float
if (abs_ai >= float_max_bits || abs_bi >= float_max_bits) {
return ((ai == 0x7F800000 || ai == 0xFF800000) && (bi == 0x7F800000 || bi == 0xFF800000)) || (abs(abs_ai - abs_bi) < 0x100000);
}
// Handle negative and positive zero as equal
if (ai == 0 && bi == 0) return 1;
// Make the integer representation ordered as a two's complement integer
if (ai < 0) ai = 0x80000000 - ai;
if (bi < 0) bi = 0x80000000 - bi;
// Compute the difference in ULPs
int32_t ulp_diff = abs(ai - bi);
return ulp_diff <= ULP_TOLERANCE;
}
int main() {
float x = 0.1f;
float y = nextafterf(x, 1.0f); // Get next representable float
if (float_almost_equal(x, y)) {
printf("Numbers are almost equal.\n");
} else {
printf("Numbers are not equal.\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment