Repository: junzis/pyModeS

Issue:
Number formatting
It is very hard to read it. Tried to use the latest release & latest commit from the repository. 
![image](https://github.com/user-attachments/assets/56586f69-5f3b-4c55-af53-7fd8a76dc8e5)
I'm using dump1090-mutability to decode the signal from RTL. The same behavior is on raw input and beast.

Discussion:
@junzis: thanks, @jbencina, for fixing this!

Solution patch:
diff --git a/src/pyModeS/decoder/bds/bds05.py b/src/pyModeS/decoder/bds/bds05.py
index 0dc8b8b..08e07c0 100644
--- a/src/pyModeS/decoder/bds/bds05.py
+++ b/src/pyModeS/decoder/bds/bds05.py
@@ -110,9 +110,8 @@ def airborne_position_with_ref(
     i = int(mb[21])
     d_lat = 360 / 59 if i else 360 / 60
 
-    j = common.floor(lat_ref / d_lat) + common.floor(
-        0.5 + ((lat_ref % d_lat) / d_lat) - cprlat
-    )
+    # From 1090 MOPS, Vol.1  DO-260C, A.1.7.5
+    j = common.floor(0.5 + lat_ref / d_lat - cprlat)
 
     lat = d_lat * (j + cprlat)
 
@@ -123,9 +122,7 @@ def airborne_position_with_ref(
     else:
         d_lon = 360
 
-    m = common.floor(lon_ref / d_lon) + common.floor(
-        0.5 + ((lon_ref % d_lon) / d_lon) - cprlon
-    )
+    m = common.floor(0.5 + lon_ref / d_lon - cprlon)
 
     lon = d_lon * (m + cprlon)
 
diff --git a/src/pyModeS/decoder/bds/bds06.py b/src/pyModeS/decoder/bds/bds06.py
index 14b2a2f..d108033 100644
--- a/src/pyModeS/decoder/bds/bds06.py
+++ b/src/pyModeS/decoder/bds/bds06.py
@@ -119,9 +119,8 @@ def surface_position_with_ref(
     i = int(mb[21])
     d_lat = 90 / 59 if i else 90 / 60
 
-    j = common.floor(lat_ref / d_lat) + common.floor(
-        0.5 + ((lat_ref % d_lat) / d_lat) - cprlat
-    )
+    # From 1090 MOPS, Vol.1  DO-260C, A.1.7.6
+    j = common.floor(0.5 + lat_ref / d_lat - cprlat)
 
     lat = d_lat * (j + cprlat)
 
@@ -132,9 +131,7 @@ def surface_position_with_ref(
     else:
         d_lon = 90
 
-    m = common.floor(lon_ref / d_lon) + common.floor(
-        0.5 + ((lon_ref % d_lon) / d_lon) - cprlon
-    )
+    m = common.floor(0.5 + lon_ref / d_lon - cprlon)
 
     lon = d_lon * (m + cprlon)
 
diff --git a/src/pyModeS/streamer/screen.py b/src/pyModeS/streamer/screen.py
index ada1bf5..0553c0d 100644
--- a/src/pyModeS/streamer/screen.py
+++ b/src/pyModeS/streamer/screen.py
@@ -70,6 +70,18 @@ class Screen(object):
             % len(self.acs),
         )
 
+
+    def round_float(self, value, max_width):
+        # Constrain a floating point number to a maximum string size.
+        # Subtract 2 to account for decimal and column spacing.
+
+        sign_size = 1 if value < 0 else 0
+        int_size = len(str(int(value)))
+        max_precision = max_width - int_size - sign_size - 2
+        rounded_value = round(value, max_precision)
+
+        return f"{rounded_value:.{max_precision}f}"
+
     def update(self):
         if len(self.acs) == 0:
             return
@@ -127,6 +139,10 @@ class Screen(object):
                         val = ""
                     else:
                         val = ac[c]
+
+                    if isinstance(val, float):
+                        val = self.round_float(val, cw)
+
                     val_str = str(val)
                     line += (cw - len(val_str)) * " " + val_str
 


Test patch:
diff --git a/tests/test_adsb.py b/tests/test_adsb.py
index 9c7f5d4..ac57bca 100644
--- a/tests/test_adsb.py
+++ b/tests/test_adsb.py
@@ -54,6 +54,15 @@ def test_adsb_airborne_position_with_ref():
     assert pos == (approx(49.81755, 0.001), approx(6.08442, 0.001))
 
 
+def test_adsb_airborne_position_with_ref_numerical_challenge():
+    lat_ref = 30.508474576271183 # Close to (360.0/59.0)*5
+    lon_ref = 7.2*5.0+3e-15
+    pos = adsb.airborne_position_with_ref(
+        "8D06A15358BF17FF7D4A84B47B95", lat_ref, lon_ref
+    )
+    assert pos == (approx(30.50540, 0.001), approx(33.44787, 0.001))
+
+
 def test_adsb_surface_position_with_ref():
     pos = adsb.surface_position_with_ref(
         "8FC8200A3AB8F5F893096B000000", -43.5, 172.5