
============================================================
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.97779766       false     true      true      
  1         25.01916948       false     true      true      
  2         25.02972687       false     true      true      
  3         25.01870257       false     true      true      
  4         24.96365349       false     true      true      
  5         25.02417787       false     true      true      
  6         25.01521257       false     true      true      
  7         25.01746188       false     true      true      
  8         25.01469876       false     true      true      
  9         24.95849519       false     true      true      
  10        25.00975313       false     true      true      
  11        24.96665774       false     true      true      

Noise amplitude: +/-0.005, abs_eps: 0.01
  sample    value             ==        abs       comb      
  0         24.99675513       false     true      true      
  1         24.9971971        false     true      true      
  2         25.00143947       false     true      true      
  3         24.99902736       false     true      true      
  4         24.99946988       false     true      true      
  5         24.99607726       false     true      true      
  6         24.99667581       false     true      true      
  7         25.00177208       false     true      true      
  8         24.99822762       false     true      true      
  9         25.00066511       false     true      true      
  10        24.997119         false     true      true      
  11        25.0030632        false     true      true      

Noise amplitude: +/-0.0005, abs_eps: 0.0001
  sample    value             ==        abs       comb      
  0         24.99998171       false     true      true      
  1         25.00043692       false     false     false     
  2         24.99991995       false     true      true      
  3         24.99953881       false     false     false     
  4         24.99997226       false     true      true      
  5         25.00001312       false     true      true      
  6         24.99969943       false     false     false     
  7         25.00025024       false     false     false     
  8         24.99970481       false     false     false     
  9         25.0004967        false     false     false     
  10        24.99993727       false     true      true      
  11        24.99984134       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.
