https://tavianator.com/2024/percent.html
[ ]
1. Home
2. Projects
3.
1. bfs
2. acap
3. bistring
4. 2024
5.
1. Rounding percentages
2. Bug hunting in Btrfs
6. 2023
7.
1. Translucent typedefs in C
2. bfs 3.0: the fastest find yet!
3. You could have invented futexes
4. Irregular expressions
8. 2022
9.
1. Fast, Branchless Ray/Bounding Box Intersections, Part 3:
Boundaries
2. Remote reboots with encrypted disks
3. Parallelizing graph search with Rayon
4. Long division
10. 2020
11.
1. Proving that 1 + 1 = 10 in Rust
2. OOMify
3. Makeover
4. Porting k-d forests to Rust
12. 2018
13.
1. spawn() of Satan
2. Cracking DHCE (Diffie-Hellman color exchange)
14. 2017
15.
1. bfs from the ground up, part 3: optimization
2. bfs from the ground up, part 2: parsing
16. 2016
17.
1. A quick trick for faster naive matrix multiplication
2. bfs from the ground up, part 1: traversal
3. The Approximating and Eliminating Search Algorithm
18. 2015
19.
1. Java autoboxing performance
2. Fast, Branchless Ray/Bounding Box Intersections, Part 2: NaNs
20. 2014
21.
1. Efficient Integer Exponentiation in C
2. Standards-compliant* alloca()
3. The Visitor Pattern in Python
4. Exact Bounding Boxes for Spheres/Ellipsoids
5. A Beautiful Ray/Mesh Intersection Algorithm
6. A Beautiful Ray/Triangle Intersection Method
7. Announcing Sangria
8. k-d Forests
9. Big Numbers
22. 2013
23.
1. Java Generics Quirks
2. Fair and Square, or How to Count to a Googol
24. 2012
25.
1. Iterating Over Binary Trees
26. 2011
27.
1. Collisions
2. Ray / Priority R-Tree Intersection
3. Priority R-Trees
4. Fast, Branchless Ray/Bounding Box Intersections
5. Fast Binary-Coded Decimal Addition and Subtraction
6. Facebook Hacker Cup Qualification Round: Double Squares
28. 2010
29.
1. Righteous hack: getting 263 - 1 points in a silly Facebook
game
2. Solving Cubic Polynomials
3. Solving Polynomials
4. .com
* Light
* Rust
* Coal
* Navy
* Ayu
tavianator.com
[ ]
Rounding percentages
2024-06-21 Tavian Barnes
Let's say you're downloading a file and you see this:
0%
How do you know the download actually started? Similarly, if you see
this:
100%
Is it actually done? Or did it download 999/1000 bytes and then hang?
I know this is a relatively minor thing, but I find myself frustrated
by UIs like this so often that I'm proposing these rules for rounding
percentages that are shown to users:
* 0% means exactly zero percent. If the user sees 0%, they can
assume that absolutely nothing has happened yet except rendering
the progress bar.
* 100% means finished. If the user sees 100%, the process is
finished, done, over, complete. They shouldn't have to wait for
anything else to happen to start using the thing. Don't show 100%
and then call fsync() or something silly.
In between those values, interpolate as normal.
There are a few ways to implement this. With (truncating) integer
division, you just have to fix up the 0% case:
>>> def percent(progress, total):
... ret = 100 * progress // total
... if ret == 0 and progress > 0:
... return 1
... else:
... return ret
...
>>> percent(0, 1000)
0
>>> percent(1, 1000)
1
>>> percent(999, 1000)
99
>>> percent(1000, 1000)
100
There's also a neat trick with floating point: the default rounding
mode is typically ties-to-even. So if we interpolate between
[0.5,99.5][0.5, 99.5][0.5,99.5] instead of [0,100][0, 100][0,100],
the endpoints will round correctly and everything else will stay
within [1,99][1, 99][1,99]:
>>> def percent(progress, total):
... return round(99 * progress / total + 0.5)
...
>>> percent(0, 1000)
0
>>> percent(1, 1000)
1
>>> percent(999, 1000)
99
>>> percent(1000, 1000)
100
(If your language has bad defaults, you may have to ask for the right
rounding mode explicitly.)