Created
February 16, 2025 21:15
-
-
Save dockimbel/e479ad63adcacb690dd80c8ebec10de9 to your computer and use it in GitHub Desktop.
C function for comparing float values that are close enough (<= 10 ULP)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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