I am trying to write an application to convert bytes to kb to mb to gb to tb. Here\'s what I have so far:
def size_format(b):
if b < 1000:
r
Here is to convert bytes to kilo, mega, tera.
#From bytes to kilo, mega, tera
def get_(size):
#2**10 = 1024
power = 2**10
n = 1
Dic_powerN = {1:'kilobytes', 2:'megabytes', 3:'gigabytes', 4:'Terabytes'}
if size <= power**2 :
size /= power
return size, Dic_powerN[n]
else:
while size > power :
n += 1
size /= power**n
return size, Dic_powerN[n]
I have improved, in my opininion, @whereisalext answer to have a somewhat more generic function which does not require one to add more if statements once more units are going to be added:
AVAILABLE_UNITS = ['bytes', 'KB', 'MB', 'GB', 'TB']
def get_amount_and_unit(byte_amount):
for index, unit in enumerate(AVAILABLE_UNITS):
lower_threshold = 0 if index == 0 else 1024 ** (index - 1)
upper_threshold = 1024 ** index
if lower_threshold <= byte_amount < upper_threshold:
if lower_threshold == 0:
return byte_amount, unit
else:
return byte_amount / lower_threshold, AVAILABLE_UNITS[index - 1]
# Default to the maximum
max_index = len(AVAILABLE_UNITS) - 1
return byte_amount / (1024 ** max_index), AVAILABLE_UNITS[max_index]
Do note that this differs slightly frrom @whereisalext's algo:
I think this is a short and succinct. The idea is based on some graph scaling code I wrote many years ago. The code snippet round(log2(size)*4)/40
does the magic here, calculating the boundaries with an increment with the power of 2**10. The "correct" implementation would be: trunc(log2(size)/10
, however then you would get strange behavior when the size is close to a new boundary. For instance datasize(2**20-1)
would return (1024.00, 'KiB'). By using round
and scaling the log2
result you get a nice cutof when approaching a new boundary.
from math import log2
def datasize(size):
"""
Calculate the size of a code in B/KB/MB.../
Return a tuple of (value, unit)
"""
assert size>0, "Size must be a positive number"
units = ("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
scaling = round(log2(size)*4)//40
scaling = min(len(units)-1, scaling)
return size/(2**(10*scaling)), units[scaling]
for size in [2**10-1, 2**10-10, 2**10-100, 2**20-10000, 2**20-2**18, 2**20, 2**82-2**72, 2**80-2**76]:
print(size, "bytes= %.3f %s" % datasize(size))
1023 bytes= 0.999 KiB
1014 bytes= 0.990 KiB
924 bytes= 924.000 B
1038576 bytes= 0.990 MiB
786432 bytes= 768.000 KiB
1048576 bytes= 1.000 MiB
4830980911975647053611008 bytes= 3.996 YiB
1133367955888714851287040 bytes= 0.938 YiB
I have quite readable function to convert bytes into greater units:
def bytes_2_human_readable(number_of_bytes):
if number_of_bytes < 0:
raise ValueError("!!! number_of_bytes can't be smaller than 0 !!!")
step_to_greater_unit = 1024.
number_of_bytes = float(number_of_bytes)
unit = 'bytes'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'KB'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'MB'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'GB'
if (number_of_bytes / step_to_greater_unit) >= 1:
number_of_bytes /= step_to_greater_unit
unit = 'TB'
precision = 1
number_of_bytes = round(number_of_bytes, precision)
return str(number_of_bytes) + ' ' + unit
A very simple solution would be:
SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
def get_readable_file_size(size_in_bytes):
index = 0
while size_in_bytes >= 1024:
size_in_bytes /= 1024
index += 1
try:
return f'{size_in_bytes} {SIZE_UNITS[index]}'
except IndexError:
return 'File too large'
good idea for me:
def convert_bytes(num):
"""
this function will convert bytes to MB.... GB... etc
"""
step_unit = 1000.0 #1024 bad the size
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < step_unit:
return "%3.1f %s" % (num, x)
num /= step_unit