#02 — Floating Point Equality Is a Lie
This commit is contained in:
261
analysis/#02 — Floating Point Equality Is a Lie/readmy.md
Normal file
261
analysis/#02 — Floating Point Equality Is a Lie/readmy.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# Analysis #02 — Floating Point Equality Is a Lie
|
||||
|
||||
## Problem
|
||||
|
||||
At interviews, you often see something like:
|
||||
|
||||
> Compare two floating point numbers and determine if they are equal.
|
||||
|
||||
Typical answer:
|
||||
|
||||
```cpp
|
||||
if (a == b) { }
|
||||
```
|
||||
|
||||
Or the “better” version:
|
||||
|
||||
```cpp
|
||||
fabs(a - b) < 1e-9
|
||||
```
|
||||
|
||||
Looks correct. In real engineering — not enough.
|
||||
|
||||
---
|
||||
|
||||
## The Real Issue
|
||||
|
||||
The problem is not that `==` is bad.
|
||||
|
||||
The problem is the assumption:
|
||||
|
||||
> There exists one correct way to compare floating point numbers.
|
||||
|
||||
There isn’t.
|
||||
|
||||
---
|
||||
|
||||
## Why `==` Fails
|
||||
|
||||
Classic example:
|
||||
|
||||
```cpp
|
||||
double a = 0.1 + 0.2;
|
||||
double b = 0.3;
|
||||
```
|
||||
|
||||
`a != b`
|
||||
|
||||
Reasons:
|
||||
- binary representation
|
||||
- rounding errors
|
||||
- accumulation of operations
|
||||
|
||||
---
|
||||
|
||||
## Why “Just Use Epsilon” Is Not Enough
|
||||
|
||||
### Scale problem
|
||||
|
||||
```cpp
|
||||
a = 1e9;
|
||||
b = a + 0.1;
|
||||
```
|
||||
|
||||
`1e-9` is meaningless here.
|
||||
|
||||
---
|
||||
|
||||
### Near-zero problem
|
||||
|
||||
```cpp
|
||||
a = 1e-12;
|
||||
b = 2e-12;
|
||||
```
|
||||
|
||||
`1e-9` is too large.
|
||||
|
||||
---
|
||||
|
||||
### Meaning problem
|
||||
|
||||
What are these values?
|
||||
|
||||
- sensor readings?
|
||||
- computed values?
|
||||
- scaled integers?
|
||||
- geometry?
|
||||
|
||||
Without context, comparison is undefined.
|
||||
|
||||
---
|
||||
|
||||
## What This Actually Tests
|
||||
|
||||
In interviews, this checks:
|
||||
|
||||
- awareness of IEEE754
|
||||
- prior exposure to the trap
|
||||
- memorized epsilon usage
|
||||
|
||||
Not real engineering thinking.
|
||||
|
||||
---
|
||||
|
||||
## Real-World Behavior
|
||||
|
||||
### Sensor example
|
||||
|
||||
```cpp
|
||||
if (temperature == target)
|
||||
```
|
||||
|
||||
System never stabilizes.
|
||||
|
||||
Reality:
|
||||
- noise
|
||||
- quantization
|
||||
- jitter
|
||||
|
||||
Solution:
|
||||
- tolerance
|
||||
- hysteresis
|
||||
- filtering
|
||||
|
||||
---
|
||||
|
||||
### Computation paths
|
||||
|
||||
```cpp
|
||||
double x = (a + b) + c;
|
||||
double y = a + (b + c);
|
||||
```
|
||||
|
||||
Different results.
|
||||
|
||||
---
|
||||
|
||||
### Scaled data (CAN-like)
|
||||
|
||||
```cpp
|
||||
raw = 1234;
|
||||
value = raw * 0.1;
|
||||
expected = 123.4;
|
||||
```
|
||||
|
||||
Comparison fails.
|
||||
|
||||
---
|
||||
|
||||
## Demo Code
|
||||
|
||||
A full demonstration program is available:
|
||||
|
||||
- examples/main.cpp
|
||||
|
||||
It shows:
|
||||
- where `==` fails
|
||||
- where fixed epsilon fails
|
||||
- why scale matters
|
||||
- how noise breaks naive logic
|
||||
- why hysteresis is often required
|
||||
|
||||
---
|
||||
|
||||
## Example Output (fill with your own results)
|
||||
|
||||
Below you can include actual output from your system.
|
||||
|
||||
```text
|
||||
[insert your real output here]
|
||||
```
|
||||
|
||||
Use this section to demonstrate:
|
||||
- how behavior changes with different eps values
|
||||
- how noise affects stability
|
||||
- differences between float and double
|
||||
- how hysteresis stabilizes the system
|
||||
|
||||
---
|
||||
|
||||
## Better Approaches
|
||||
|
||||
### Absolute
|
||||
|
||||
```cpp
|
||||
fabs(a - b) < abs_eps
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Relative
|
||||
|
||||
```cpp
|
||||
fabs(a - b) < rel_eps * max(fabs(a), fabs(b))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Combined
|
||||
|
||||
```cpp
|
||||
fabs(a - b) <= max(abs_eps, rel_eps * max(fabs(a), fabs(b)))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Or Avoid Float
|
||||
|
||||
Compare:
|
||||
- raw values
|
||||
- fixed-point
|
||||
- integers
|
||||
|
||||
---
|
||||
|
||||
### Or Change the Question
|
||||
|
||||
Instead of:
|
||||
|
||||
> Are values equal?
|
||||
|
||||
Ask:
|
||||
|
||||
> Are they close enough for the system?
|
||||
|
||||
---
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- Using `==`
|
||||
- Fixed epsilon everywhere
|
||||
- Only relative error
|
||||
- Only absolute error
|
||||
- Blind rounding
|
||||
|
||||
---
|
||||
|
||||
## Key Takeaway
|
||||
|
||||
Floating point comparison is not a trick.
|
||||
|
||||
It is a modeling problem.
|
||||
|
||||
---
|
||||
|
||||
## Project Perspective
|
||||
|
||||
Does this problem exist in real engineering?
|
||||
|
||||
Yes.
|
||||
|
||||
In interview form?
|
||||
|
||||
Almost never.
|
||||
|
||||
Because real systems have:
|
||||
- noise
|
||||
- scale
|
||||
- constraints
|
||||
- consequences
|
||||
|
||||
And no universal epsilon.
|
||||
Reference in New Issue
Block a user