Maths - Memory Calculation

Blitz3D Forums/Blitz3D Beginners Area/Maths - Memory Calculation

_PJ_(Posted 2013) [#1]
I broke the maths...

I was trying to optimise a little function that would display a number of bytes in the most 'sensible' format (i.e Megabytes, Gigabytes etc.)
However, I managed to break it completely and now I can't even get it back to its previous state.

I would love it if anybody can advise me on:
a) If using logarithms etc. is really a fast way
b) If so, How to fix it? (please, thank you very much indeed!)

The current mess is:



A clean, working, but unoptimised format is:



Yasha(Posted 2013) [#2]
Y'all'r logarithm is backwards, it should be returning Log(n4_Bytes) / Log(1024).


Other things to consider:

-- is optimising this function important? Have you profiled? More importantly, does the combined weight of all the math outweigh even a single string construction? Normally string operations should be considered a performance write-off; associated math therefore can be as clear as you want.

-- ignoring the above point, the "optimised" version is actually better in my opinion as (as long as you understand Log) it's much closer to actually doing what you want, which is to work out a code based on the number of digits, not to evaluate some division result thing.

-- the Log version is also substantially less likely to be affected by precision and rounding limitations, as the single Log operation will continue to give correct (for your needs) results no matter how borked the accuracy gets.

-- as you have demonstrated, it's easier to add both extra suffix codes, and an exception mode ("I don't understand numbers that big Dave"), with single case/default lines, no extra ops needed.

-- since this is a string operation, if I were you I would ditch the attempt to create a result string mathematically and instead use f_Mag to string-slice the digits you want. Again because it's closer to what your intention is: mathematical results aren't the goal here. It's also guaranteed not to be affected by precision limitations. (EDIT: actually that's stupid, what I would really do is use integer division in a loop. Either way, avoid using floats in this step, not necessary.)

-- take note that B3D integers are limited to 32-bits, which realistically is just not enough to meaningfully describe data sizes in this day and age (same problem as with your AvailVidMem thread). You might want to think about some way of hacking long integers into this (and that other thread), or even using arbitrary-precision numbers (AKA string numbers), which are quite easy to code in B3D. (Side note: the fact that B3D's floats are limited to only 23 bits of precision is, surprisingly, unlikely to cause problems, simply because you're truncating the end result figure to well below that anyway!)


Oh and we had a big argument over this a while back, but the unit you're using here - powers of 1024 - are the IEC binary prefix forms which can be unambiguously referred to as kibibytes, mebibytes, etc. with the symbols KiB, MiB...

It is generally safe to refer to the binary-scale units using ambiguous names, because 1) they're larger, so you're reporting a smaller size, which is more conservative and therefore won't screw the user if they assume the other unit; and 2) they're the only standardised form anyway (there is no actual definition of megabyte etc., and not even any obvious right answer; at least three definitions are in common use).

But do be aware that because of the multiple unit systems, the answers you give using one of them may end up being different from any results the users get from a second system that uses inconsistent math; this is why it's generally best to use the XiB suffix where possible.


_PJ_(Posted 2013) [#3]
Thanks for a great response, Yasha.


it should be returning Log(n4_Bytes) / Log(1024).


:) Thanks! It's so easy to get confused after chopping the code about so much, I really didn't see this!

I know that I wanted to use logs as that prevents a lot of FP errors, but more importantly, when it comes to manipulating the strings etc. using Logs avoids a lot of instances and possibilities where standard form is used (making identifyiugn the position of the decimal point etc. a real pain)

My reasons for wanting this in the first place is simply for debugging purposes, and so I imagine is ultimately unnecessary, since debugging logs and outputs etc is gonna slow things down no matter what. I should have said just a neater code, rather than "optimised" , probably!

It came about because it could get confusing sometimes with the large numbers, and easy to mistake, say, 7 characters for 8 so I wanted to be able to visualise results as Mb, Kb etc. (Or as you noted, KiB, MiB etc.)

And yeah, you are indeed correct about those KiB units - But as it was for my own personal debugging routines I was just happy keeping the (technically incorrect) Kb notation, but I appreciate you pointing it out all the same and it's a simp[le matter to just insert the 'i' where required!


what I would really do is use integer division in a loop


A much earlier version had an approach like this: was this how you meant?