On my platform, unsigned long long is 64 bits (8 bytes). Suppose I have two such variables:
unsigned long long partialSize;
unsigned long long totalSize;
//somehow determine partialSize and totalSize
How can I reliably determine how many percentages (rounded to a nearby integer) partialSize is of totalSize? (If possible, it would be nice if I wouldn’t have to assume that the former is less than the latter, but if I really have to make this assumption, it’s fine. But we can, of course, assume that both are non-negative.)
For example, is the following code completely bulletproof? My fear is that it contains some kind of rounding, casting, or conversion errors that could cause the ratio to go out of whack under some conditions.
unsigned long long ratioPercentage
= (unsigned long long)( ((double)partialSize)/((double)totalSize) * 100.0 );
It’s not completely bullet-proof.
doublemantissae are only 53 bits (52 + 1 implicit), so if your numbers are larger than2^53, the conversion todoublewill in general introduce rounding errors. However, the rounding errors are very small in relation to the numbers itself, so a percentage calculation resulting in an integer value will introduce more inaccuracy than the conversion.A possibly more serious concern is that this will always round downwards, e.g. for
totalSize = 1000andpartialSize = 99, it will return9rather than the closer value10. You can get better rounding by adding0.5before casting tounsigned long long.You can get exact results using only integer arithmetic (if the final result doesn’t overflow), it’s fairly easy if
partialSizeis not too large:Easy modifications if you want floor, ceiling or round-half-to-even.
It’s okay if
totalSize >= 100andULLONG_MAX / 100 >= partialSize % totalSize,It gets more fiddly in the other cases, I’m not keen on doing it, but I could be persuaded if you need it.