It is currently October 19th, 2020, 9:33 pm
Converting Bytes (AutoScale Alternative)

 Posts: 51
 Joined: July 12th, 2020, 7:47 am
Re: Converting Bytes (AutoScale Alternative)
Oh great, i quess it will save me in a places where i cannot use autoscale. Really helpful, thank you.

 Rainmeter Sage
 Posts: 11575
 Joined: October 11th, 2010, 6:27 pm
 Location: Gheorgheni, Romania
Re: Converting Bytes (AutoScale Alternative)
And do you have any question related to your code? If you have, post the code please.

 Posts: 2760
 Joined: February 27th, 2015, 2:38 pm
 Location: Terra Yincognita
Re: Converting Bytes (AutoScale Alternative)
Yeah, that was my starting point as well, when I set up the solution used in my (tooltip featured) skins years ago, but it has several mistakes and drawbacks:ikarus1969 wrote: ↑September 22nd, 2020, 9:51 am I want to throw in a solution provided by user smurfier in this thread/post about the recycle bin introducing the "scary math" for getting scale and the scaled size for a number of bytes.
a slightly adapted excerpt from the post:
...
 values between 0 and 1 give wrong results (try 0.25, for example; that's because Log() is negative for all the values greater than 0 and less than 1)
 negative values yield errors (try 15, for example; sure, it's unlikely to have to scale negative values, but still)
 values equal to the scale are not converted (try 1024, for example; it is left as 1024, when it should be 1, since 1024 is 1 kb)
 decimals don't get to the final result if they are 0 (try 1029, for example; it should be 1.00, but it is 1)
 two measures are needed in his implementation, when just one is enough (the "B" suffix can be added in the meter, just like for builtin autoscaling)
 his implementation only does fixed scaling to 1024, even though variable scaling (e.g. the equivalent of AutoScale option, to whatever number) is possible
These are clear when changing the Formula from [Measure_Bin_Size] in the code below and comparing the builtin autoscale with the scale in the tooltip:
Code: Select all
; Kilobyte (kB) = 1024
; Megabyte (MB) = 1048576 or 1024**2
; Gigabyte (GB) = 1073741824 or 1024**3
; Terabyte (TB) = 1099511627776 or 1024**4
[Variables]
Decimals=2
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255
Measures
[Measure_Bin_Size]
Measure=Calc
Formula=1024
[Measure_Scale]
Measure=CALC
Formula=Measure_Bin_Size = 0 ? 1 : CEIL(LOG(Measure_Bin_Size) / (10 * LOG(2)))
Substitute="1":"B","2":"kB","3":"mB","4":"gB","5":"tB","6":"pB","7":"eB","8":"zB","9":"yB"
DynamicVariables=1
[Measure_Scaled_Size]
Measure=CALC
Formula=ROUND(Measure_Bin_Size / 1024 **(Measure_Scale  1), #Decimals#)
DynamicVariables=1
Meters
[Meter_Scaled_Size]
Meter=STRING
X=0
Y=0
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
MeasureName=Measure_Bin_Size
AutoScale=1
NumOfDecimals=#Decimals#
Text="Inbuilt Scale = %1"
TooltipText="Custom Scale = [Measure_Scaled_Size] [Measure_Scale]"
DynamicVariables=1
Code: Select all
[Variables]
Scale=1024
Decimals=2
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255
Measures
[RawNumber]
Measure=Calc
Formula=8618111
[ScaledNumber]
Measure=Calc
Formula=Sgn(RawNumber=0?1:RawNumber)*(Round(Abs(RawNumber)/#Scale#**Trunc(Log(Abs(RawNumber)<1?1:Abs(RawNumber))/Log(#Scale#)),#Decimals#)+(Trunc(Log(Abs(RawNumber)<1?1:Abs(RawNumber))/Log(#Scale#))+1)*(10**(#Decimals#2)))
RegExpSubstitute=1
Substitute="^(.*\..{#Decimals#}).{1}(.{1}).*$":"\1\2","1$":" ","2$":" k","3$":" M","4$":" G","5$":" T","6$":" P","7$":" E","8$":" Z","9$":" Y"
DynamicVariables=1
Meters
[ScaledNumbers]
Meter=STRING
X=0
Y=0
FontFace=Consolas
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
MeasureName=RawNumber
AutoScale=1
NumOfDecimals=#Decimals#
Text="Inbuilt Scale = %1B"
TooltipText="Custom Scale = [ScaledNumber]B"
DynamicVariables=1
You do not have the required permissions to view the files attached to this post.

 Posts: 392
 Joined: February 28th, 2011, 3:20 pm
 Location: Vienna, Austria
Re: Converting Bytes (AutoScale Alternative)
Thanks for sharing your solution (again?)! I definitely will adapt my skins  and yes it is scaryYincognito wrote: ↑September 23rd, 2020, 5:09 pm So, the solution I extensively use in my skins is an adapted, corrected and much more flexible one, at the expense of yet more "scary math" :

 Posts: 2760
 Joined: February 27th, 2015, 2:38 pm
 Location: Terra Yincognita
Re: Converting Bytes (AutoScale Alternative)
Yeah, the last time I shared it, it was good but still had some minor flaws, e.g. it didn't cover negative values and didn't convert the values equal to the scale (I discovered the latter while preparing to post it here, actually). That's why I said seeing this post was really positive as I perfected the solution  so it helped me as well.ikarus1969 wrote: ↑September 23rd, 2020, 6:45 pm Thanks for sharing your solution (again?)! I definitely will adapt my skins  and yes it is scary
Well, my regexes are scary, my formulas are scary, my code is "hideously complicated" as someone likes to say, but they all work, LOL. To me, that's the most important thing  and believe me, I would have made it less scary if I could, but math is math, it has its own rules... By the way, the formula is shorter if you don't cover the negative values, as the Sgn(...) and the Abs() parts are not needed then. Everything revolves around Log(RawNumber)/Log(#Scale#), in simplified terms, really, and adding a 0.___0N to the result in order to store the numerical codes of k, M, G, T, ... which are then converted to the actual letters in the Substitute.
In other words, if you skip the repetitive exception handling stuff, it's:
Round(RawNumber/#Scale#**Trunc(Log(RawNumber)/Log(#Scale#)),#Decimals#) < this is the actual scaled value
+
(Trunc(Log(RawNumber)/Log(#Scale#))+1)*(1/10**(#Decimals#+2)) < this is a fractional numerical suffix to store the k, M, G, ... "codes"
It becomes much easier to understand if you replace the measure and variable names with actual numbers. It's also useful to wrap your head around the concept that in the base 10 that we humans use, the (base 10) Log(x) more or less counts how many digits are either before (when Log(x) is positive) or after (when Log(x) is negative) the decimal point (aka .). So, in a way, by doing Log(RawNumber)/Log(#Scale#) we divide how many digits before the decimal point RawNumber has to how many digits before the decimal point the Scale has, in order to get how many Scale digits RawNumber has.
For example, if we want to scale 5 700 000 by a factor of 1 000 we have: Log(1 000)=3 so there are 3+1 digits in the one thousand we use as scale, and Log(5 700 000)=6.75 so there are 6+1 digits in the original number; since we scale by 1 000 in this simplified example, we want to find out to which number we have to divide the original value to get the scaled value, and that is Scale^Trunc(6.75/3), aka 1 000 ^ 2, aka 1 000 000. We therefore get 5 700 000 / 1 000 000 = 5.7 to which we append the appropriate "M" (i.e. mega) suffix later on, using a similar approach.