
============================================================
1. Basic classic: 0.1 + 0.2 != 0.3
============================================================
  a                           : 0.30000000000000004
  b                           : 0.29999999999999999
  abs(a - b)                  : 5.5511151231257827e-17
  a == b                      : false
  abs eps = 1e-12             : true
  abs eps = 1e-9              : true
  combined                    : true

============================================================
2. Large numbers: fixed absolute epsilon becomes useless
============================================================
  a                           : 1000000000
  b                           : 1000000000.1
  abs(a - b)                  : 0.10000002384185791
  a == b                      : false
  abs eps = 1e-12             : false
  abs eps = 1e-9              : false
  abs eps = 1e-3              : false
  rel eps = 1e-12             : false
  rel eps = 1e-9              : true
  combined                    : true

============================================================
3. Very small numbers: fixed absolute epsilon can be too large
============================================================
  a                           : 9.9999999999999998e-13
  b                           : 2e-12
  abs(a - b)                  : 9.9999999999999998e-13
  a == b                      : false
  abs eps = 1e-9              : true
  abs eps = 1e-12             : true
  rel eps = 1e-9              : false
  rel eps = 0.5               : true
  combined                    : false

============================================================
4. Near zero: relative comparison alone is weak
============================================================
  a                           : 0
  b                           : 1.0000000000000001e-15
  abs(a - b)                  : 1.0000000000000001e-15
  a == b                      : false
  rel eps = 1e-6              : false
  abs eps = 1e-12             : true
  combined                    : true

============================================================
5. Same math on paper, different result in floating point
============================================================
  x = (a + b) + c             : 1
  y = a + (b + c)             : 0
  abs(x - y)                  : 1
  x == y                      : false
  combined                    : false

============================================================
6. Accumulation of error: repeated addition
============================================================
  x                           : 100000.00000133288
  y                           : 100000
  abs(x - y)                  : 1.3328826753422618e-06
  x == y                      : false
  abs eps = 1e-9              : false
  abs eps = 1e-6              : false
  combined                    : false

============================================================
7. float vs double: same idea, different precision
============================================================
  float a                     : 0.30000001
  float b                     : 0.30000001
  float abs diff              : 0
  float a == b                : true

  double a                    : 0.30000000000000004
  double b                    : 0.29999999999999999
  double abs diff             : 5.5511151231257827e-17
  double a == b               : false

============================================================
8. Sensor-like values: 'equal' is often the wrong question
============================================================

Noise amplitude: +/-0.050000000000000003, abs_eps: 0.10000000000000001
  sample    value             ==        abs       comb      
  0         24.97471804       false     true      true      
  1         25.0413491        false     true      true      
  2         24.99852989       false     true      true      
  3         24.99317494       false     true      true      
  4         25.00292729       false     true      true      
  5         25.03122934       false     true      true      
  6         24.97063462       false     true      true      
  7         24.9619692        false     true      true      
  8         24.99279928       false     true      true      
  9         24.97964776       false     true      true      
  10        25.04053616       false     true      true      
  11        25.0353959        false     true      true      

Noise amplitude: +/-0.005, abs_eps: 0.01
  sample    value             ==        abs       comb      
  0         25.00020134       false     true      true      
  1         25.00382071       false     true      true      
  2         25.00383611       false     true      true      
  3         24.99614752       false     true      true      
  4         25.00265027       false     true      true      
  5         25.00074494       false     true      true      
  6         24.99856782       false     true      true      
  7         25.00364029       false     true      true      
  8         25.00150722       false     true      true      
  9         25.00310794       false     true      true      
  10        25.00211411       false     true      true      
  11        25.00197054       false     true      true      

Noise amplitude: +/-0.0005, abs_eps: 0.0001
  sample    value             ==        abs       comb      
  0         25.00034068       false     false     false     
  1         24.99978583       false     false     false     
  2         24.99965013       false     false     false     
  3         25.00030996       false     false     false     
  4         25.00044598       false     false     false     
  5         25.00007675       false     true      true      
  6         25.00043085       false     false     false     
  7         24.99969316       false     false     false     
  8         24.99999024       false     true      true      
  9         24.99991615       false     true      true      
  10        25.00012491       false     false     false     
  11        24.99951951       false     false     false     

============================================================
9. Scaled integer values: often better to compare raw domain
============================================================
  raw_value                   : 1234
  raw_target                  : 1234
  raw_value == raw_target     : true

  scaled_value                : 123.40000000000001
  scaled_target               : 123.40000000000001
  abs diff                    : 0
  scaled_value == scaled_target: true
  combined                    : true

  Note: if your system is naturally discrete, comparing raw units can be simpler
  and more honest than converting everything to floating point too early.

============================================================
10. Rounding is not a universal fix
============================================================
  a                           : 1.0048999999999999
  b                           : 1.0051000000000001

  round(a, 2)                 : 1
  round(b, 2)                 : 1.01
  equal after round(2)        : false

  round(a, 3)                 : 1.0049999999999999
  round(b, 3)                 : 1.0049999999999999
  equal after round(3)        : true

  Rounding may hide differences or invent equality depending on chosen precision.

============================================================
11. Hysteresis: in real systems you often want state logic, not equality
============================================================
  step    value       simple_ctrl     hyst_ctrl       
  0       24.92       HEATER ON       HEATER ON       
  1       24.97       HEATER ON       HEATER ON       
  2       25.01       HEATER OFF      HEATER ON       
  3       25.05       HEATER OFF      HEATER ON       
  4       24.99       HEATER ON       HEATER ON       
  5       25.08       HEATER OFF      HEATER ON       
  6       25.11       HEATER OFF      HEATER OFF      
  7       25.06       HEATER OFF      HEATER OFF      
  8       24.98       HEATER ON       HEATER OFF      
  9       24.91       HEATER ON       HEATER OFF      
  10      24.89       HEATER ON       HEATER ON       
  11      24.95       HEATER ON       HEATER ON       
  12      25.02       HEATER OFF      HEATER ON       
  13      25.12       HEATER OFF      HEATER OFF      
  14      25.07       HEATER OFF      HEATER OFF      
  15      24.93       HEATER ON       HEATER OFF      

  This is the key engineering point:
  sometimes the answer is not a better equality test,
  but a better control model.

Done.
