Fix a rounding bug in display of data sizes
authorJoey Hess <joeyh@joeyh.name>
Fri, 30 Jul 2021 13:56:04 +0000 (09:56 -0400)
committerJoey Hess <joeyh@joeyh.name>
Fri, 30 Jul 2021 13:56:04 +0000 (09:56 -0400)
Eg, showImprecise 1 1.99 returned "1.1" rather than "2". The 9 rounded
upward to 10, and that was wrongly used as the decimal, rather than
carrying the 1.

Sponsored-by: Jack Hill on Patreon
CHANGELOG
Utility/HumanNumber.hs
doc/bugs/git-annex_info_rounding_error.mdwn
doc/bugs/git-annex_info_rounding_error/comment_1_37079e9f024b048fb0074683f9037d19._comment [new file with mode: 0644]

index aa0e3a79b846c75415eec252770ad0ab988345d7..44d25e8e774b198cc065246ddc14b6112048adef 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -22,6 +22,7 @@ git-annex (8.20210715) UNRELEASED; urgency=medium
   * Fix bug that could prevent pointer files from being populated,
     in a repository that was upgraded from v7.
   * fsck: Detect and correct stale or missing inode caches.
+  * Fix a rounding bug in display of data sizes.
 
  -- Joey Hess <id@joeyh.name>  Wed, 14 Jul 2021 14:26:36 -0400
 
index 6143cef10594297ffe6c2773022fb41a9482a10b..04a18b0be0565b71dc3692ac7097ff17caa48555 100644 (file)
@@ -1,6 +1,6 @@
 {- numbers for humans
  -
- - Copyright 2012-2013 Joey Hess <id@joeyh.name>
+ - Copyright 2012-2021 Joey Hess <id@joeyh.name>
  -
  - License: BSD-2-clause
  -}
@@ -11,11 +11,15 @@ module Utility.HumanNumber (showImprecise) where
  - of decimal digits. -}
 showImprecise :: RealFrac a => Int -> a -> String
 showImprecise precision n
-       | precision == 0 || remainder == 0 = show (round n :: Integer)
-       | otherwise = show int ++ "." ++ striptrailing0s (pad0s $ show remainder)
+       | precision == 0 || remainder' == 0 = show (round n :: Integer)
+       | otherwise = show int' ++ "." ++ striptrailing0s (pad0s $ show remainder')
   where
        int :: Integer
        (int, frac) = properFraction n
        remainder = round (frac * 10 ^ precision) :: Integer
+       (int', remainder')
+               -- carry the 1
+               | remainder == 10 ^ precision = (int + 1, 0)
+               | otherwise = (int, remainder)
        pad0s s = replicate (precision - length s) '0' ++ s
        striptrailing0s = reverse . dropWhile (== '0') . reverse
index 4fa5d3271cf69d7e23def702e869194dae06e02a..0ad7393fd803d4a9e0d36899cb71e8c36afb827d 100644 (file)
@@ -45,3 +45,5 @@ All remotes above sit on 2tb disk drives, which are filled as much as possible.
 
 
 Thank you for all your time creating and maintaining such a usefull software!
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/bugs/git-annex_info_rounding_error/comment_1_37079e9f024b048fb0074683f9037d19._comment b/doc/bugs/git-annex_info_rounding_error/comment_1_37079e9f024b048fb0074683f9037d19._comment
new file mode 100644 (file)
index 0000000..4c45784
--- /dev/null
@@ -0,0 +1,70 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2021-07-30T12:59:46Z"
+ content="""
+I am confused by the output you show, because 2147483647 is not any number
+of terabytes. It is a couple of gigabytes. This makes me suspect you
+arrived at that number in some mistaken way.
+
+Also, when git-annex displays "TB", it's talking about TeraBytes, not
+TebiBytes (TiB). But your divisions by 1024 is calulating the latter, not the
+former. (Well, actually it's calculating gibibytes..)
+
+If there is a bug, it's presumably in Utility.HumanNumber.showImprecise,
+which does some tricky rounding of decimals.
+
+Here's a few simple tests:
+
+       # ghci Utility/DataUnits.hs
+       ghci> roughSize storageUnits  True 1000000000000
+       "1 TB"
+       ghci> roughSize storageUnits  True 1099511627776
+       "1.1 TB"
+
+Those are the correct results for an even terabyte and a tebibyte,
+displayed as terabytes. Now trying the number you provided to see what
+git-annex info will display:
+
+       ghci> roughSize storageUnits True 2147483647
+       "2.15 GB"
+
+units confirms that is the correct value, after rounding the decimal:
+
+       # units
+       You have: 2147483647 bytes
+       You want: gigabytes
+               * 2.1474836
+               / 0.46566129
+
+aIt's also almost exactly 2 gibibytes:
+
+       You have: 2147483647 bytes
+       You want: gibibytes
+               * 2
+               / 0.5
+
+The actual value is 1 byte less than 2, if I do my manual math correctly:
+       2^30*2 = 2147483648 = 2147483647+1
+
+Asking git-annex for the same using memoryUnits which are the SI units:
+
+       ghci> roughSize memoryUnits False 2147483647
+       "1.1 gibibytes"
+
+Well, this final result looks wrong, and indeed what's going on is
+similar to what you hypothesized:
+
+       ghci> roughSize' memoryUnits False 10 2147483647
+       "1.9999999991 gibibytes"
+       ghci> showImprecise 10 1.9999999990686774
+       "1.9999999991"
+       ghci> showImprecise 2 1.9999999990686774
+       "1.1"
+       ghci> round 0.9999999990686774 * (10^2)
+       100
+
+So indeed showImprecise is forgetting to carry the 1.
+
+Excellent diagnosis, but next time, show your work. ;-)
+"""]]