A small freedom area.

Smart and simple progress value hack

Thu 31 Mar 2011

prog, fapfapfap, fun

Lately at work, we were wondering how to compute a simple progress value (let's say for a download in our case). We have in input a float value in the range [0.0;100.0], and we want to display the percent in integer (it's generally handy if we want to reuse it when dealing with pixels). The quick and dirty method would be:

return (int)v;

or if you want some rounding:

return (int)(v+.5f);

But this is sometimes not enough. Indeed, we would like to make a distinction between a download of a big file that has just started, and a download stalled at 0% with not a single byte received. And in the same time, we don't want a near-the-end download at 99.9% considered done.

Here is my current solution:

return (int)v + !(int)v - !v;

and with the comments:

#include <stdio.h>
#define P(v) printf("v=%-6.1f p=%d\n", v, p(v))

int p(float v) { return (int)v + !(int)v - !v; }

             //    intbase +  range01  -   iszero    =    p

int main() { //    (int)v     !(int)v       !v
    P(0.);   //      0     +     1     -     1       =    0
    P(0.3);  //      0     +     1     -     0       =    1
    P(0.7);  //      0     +     1     -     0       =    1
    P(1.1);  //      1     +     0     -     0       =    1
    P(1.5);  //      1     +     0     -     0       =    1
    P(21.1); //     21     +     0     -     0       =   21
    P(31.6); //     31     +     0     -     0       =   31
    P(99.3); //     99     +     0     -     0       =   99
    P(99.7); //     99     +     0     -     0       =   99
    P(100.); //    100     +     0     -     0       =  100
    return 0;
}

This is enough for our case, but you may want to add a rounding level. You can, but it gets complicated pretty quickly (for not much benefit), especially if you want to avoid ternary.

index