我在重构一些旧代码时发现以下代码行,用于将字节转换为GB。
decimal GB = KB / 1024 / 1024 / 1024;
有没有更好的方法来重构下面这段代码?
更新
我想说的是字节转千兆字节。我给出了错误的信息。
我在重构一些旧代码时发现以下代码行,用于将字节转换为GB。
decimal GB = KB / 1024 / 1024 / 1024;
有没有更好的方法来重构下面这段代码?
更新
我想说的是字节转千兆字节。我给出了错误的信息。
我在这里开发了这种方法,适用于TB。
private static string FormatBytes(long bytes)
{
string[] Suffix = { "B", "KB", "MB", "GB", "TB" };
int i;
double dblSByte = bytes;
for (i = 0; i < Suffix.Length && bytes >= 1024; i++, bytes /= 1024)
{
dblSByte = bytes / 1024.0;
}
return String.Format("{0:0.##} {1}", dblSByte, Suffix[i]);
}
如果精确度不是很重要,可以使用double:
double gb = kb / 1048576D
我同意Pavel的看法 - 实际上,没有必要重构这段代码……事实上,如果这是你的代码库中最大的问题,那么我认为你可能正在使用编写得最好的软件。
原始代码简洁易读,变量名合理,自我说明性强;我不会对其进行修改。
如果您一定要重构代码,可以在数字类型上创建一组扩展方法:
public static double BytesToKilobytes(this Int32 bytes)
{
return bytes / 1024d;
}
public static double BytesToMegabytes(this Int32 bytes)
{
return bytes / 1024d / 1024d;
}
public static double KilobytesToBytes(this double kilobytes)
{
return kilobytes * 1024d;
}
//You can then do something like:
double filesize = 32.5d;
double bytes = filesize.KilobytesToBytes();
但是,除非你的代码几乎只是将字节转换为千字节等,否则所有这些都只会使智能感知变得混乱,而没有真正的收益。
我写了一个小实用程序类,可以在不同的单位之间进行转换,希望对您有帮助。
#region StorageDifferential
/// <summary>
/// Converts between Base 2 or Base 10 storage units [TB, GB, MB, KB, Bytes]
/// </summary>
public enum Differential : int
{
/// <summary>
/// Convert Bytes to Kilobytes
/// </summary>
ByteToKilo,
/// <summary>
/// Convert Bytes to Megabytes
/// </summary>
ByteToMega,
/// <summary>
/// Convert Bytes to Gigabytes
/// </summary>
ByteToGiga,
/// <summary>
/// Convert Bytes to Teraytes
/// </summary>
ByteToTera,
/// <summary>
/// Convert Kilobytes to Bytes
/// </summary>
KiloToByte,
/// <summary>
/// Convert Kilobytes to Megabytes
/// </summary>
KiloToMega,
/// <summary>
/// Convert Kilobytes to Gigabytes
/// </summary>
KiloToGiga,
/// <summary>
/// Convert Kilobytes to Terabytes
/// </summary>
KiloToTera,
/// <summary>
/// Convert Megabytes to Bytes
/// </summary>
MegaToByte,
/// <summary>
/// Convert Megabytes to Kilobytes
/// </summary>
MegaToKilo,
/// <summary>
/// Convert Megabytes to Gigabytes
/// </summary>
MegaToGiga,
/// <summary>
/// Convert Megabytes to Terabytes
/// </summary>
MegaToTera,
/// <summary>
/// Convert Gigabytes to Bytes
/// </summary>
GigaToByte,
/// <summary>
/// Convert Gigabytes to Kilobytes
/// </summary>
GigaToKilo,
/// <summary>
/// Convert Gigabytes to Megabytes
/// </summary>
GigaToMega,
/// <summary>
/// Convert Gigabytes to Terabytes
/// </summary>
GigaToTerra,
/// <summary>
/// Convert Terabyte to Bytes
/// </summary>
TeraToByte,
/// <summary>
/// Convert Terabyte to Kilobytes
/// </summary>
TeraToKilo,
/// <summary>
/// Convert Terabytes to Megabytes
/// </summary>
TeraToMega,
/// <summary>
/// Convert Terabytes to Gigabytes
/// </summary>
TeraToGiga,
}
#endregion
#region Storage Sizes
/// <summary>
/// Enumeration of recognized storage sizes [in Bytes]
/// </summary>
public enum StorageSizes : long
{
/// <summary>
/// Base 10 Conversion
/// </summary>
KILOBYTE = 1000,
MEGABYTE = 1000000,
GIGABYTE = 1000000000,
TERABYTE = 1000000000000,
/// <summary>
/// Base 2 Conversion
/// </summary>
KIBIBYTE = 1024,
MEBIBYTE = 1048576,
GIBIBYTE = 1073741824,
TEBIBYTE = 1099511627776,
}
#endregion
#region StorageBase
/// <summary>
/// Storage powers 10 based or 1024 based
/// </summary>
public enum StorageBase : int
{
/// <summary>
/// 1024 Base power, Typically used in memory measurements
/// </summary>
BASE2,
/// <summary>
/// 10 Base power, Used in storage mediums like harddrives
/// </summary>
BASE10,
}
#endregion
/// <summary>
/// Convert between base 1024 storage units [TB, GB, MB, KB, Byte]
/// </summary>
public static class StorageConverter
{
/// <summary>
/// Convert between base 1024 storage units [TB, GB, MB, KB, Byte]
/// </summary>
/// <param name="SizeDifferential">Storage conversion differential [enum]</param>
/// <param name="UnitSize">Size as mutiple of unit type units [double]</param>
/// <param name="BaseUnit">Size of the base power [enum]</param>
/// <returns>Converted unit size [double]</returns>
public static double Convert(Differential SizeDifferential, double UnitSize, StorageBase BaseUnit = StorageBase.BASE10)
{
if (UnitSize < 0.000000000001) return 0;
double POWER1 = 1000;
double POWER2 = 1000000;
double POWER3 = 1000000000;
double POWER4 = 1000000000000;
if (BaseUnit == StorageBase.BASE2)
{
POWER1 = 1024;
POWER2 = 1048576;
POWER3 = 1073741824;
POWER4 = 1099511627776;
}
switch (SizeDifferential)
{
case Differential.ByteToKilo:
return UnitSize / POWER1;
case Differential.ByteToMega:
return UnitSize / POWER2;
case Differential.ByteToGiga:
return UnitSize / POWER3;
case Differential.ByteToTera:
return UnitSize / POWER4;
case Differential.KiloToByte:
return UnitSize * POWER1;
case Differential.KiloToMega:
return UnitSize / POWER1;
case Differential.KiloToGiga:
return UnitSize / POWER2;
case Differential.KiloToTera:
return UnitSize / POWER3;
case Differential.MegaToByte:
return UnitSize * POWER2;
case Differential.MegaToKilo:
return UnitSize * POWER1;
case Differential.MegaToGiga:
return UnitSize / POWER1;
case Differential.MegaToTera:
return UnitSize / POWER2;
case Differential.GigaToByte:
return UnitSize * POWER3;
case Differential.GigaToKilo:
return UnitSize * POWER2;
case Differential.GigaToMega:
return UnitSize * POWER1;
case Differential.GigaToTerra:
return UnitSize / POWER1;
case Differential.TeraToByte:
return UnitSize * POWER4;
case Differential.TeraToKilo:
return UnitSize * POWER3;
case Differential.TeraToMega:
return UnitSize * POWER2;
case Differential.TeraToGiga:
return UnitSize * POWER1;
}
return 0;
}
}
这是对JLopez优秀回答的小改进。在这里,您可以选择是否具有单位说明,千字节单位使用小写的"k"(大写的"k"用于开尔文)。
//note: this is the JLopez answer!!
/// <summary>
/// Return size in human readable form
/// </summary>
/// <param name="bytes">Size in bytes</param>
/// <param name="useUnit ">Includes measure unit (default: false)</param>
/// <returns>Readable value</returns>
public static string FormatBytes(long bytes, bool useUnit = false)
{
string[] Suffix = { " B", " kB", " MB", " GB", " TB" };
double dblSByte = bytes;
int i;
for (i = 0; i < Suffix.Length && bytes >= 1024; i++, bytes /= 1024)
{
dblSByte = bytes / 1024.0;
}
return $"{dblSByte:0.##}{(useUnit ? Suffix[i] : null)}";
}
个人认为应该这样写:decimal GB = KB / (1024 * 1024);
但是按照原来的代码编写也没有必要重构。
嗯,这个公式是错误的(一GB只有大约一百万KB,而不是十亿),但除此之外,它还是正确的。任何习惯使用这些数字的人都会知道它的含义。
需要注意的一件事情(我不知道C#是否存在这个问题)是,如果x
不是基本类型,编译器可能无法优化x/1024/1024
。对于C和整数而言,编译器可以轻松地将其转换为“盲目快速移位20位”的指令。
如果decimal
是一个类而不是基本类型,编译器可能需要执行两个除法操作。这是否对速度产生任何真正的影响(或者它是否发生)超出了我的知识范围。
我建议更改实际变量名称。这对编译后的代码没有任何实际影响,但我更喜欢较长的变量名而不是缩写,所以我会选择kiloBytes/gigaBytes
或类似的名称。根据您的编码标准,KB/GB
太容易与常量混淆。
decimal GB = KB / (1024 * 1024);
decimal GB = KB / (1000 * 1000);
理论上,这样做更快(预先计算常数以进行乘法而不是除法)。可能没有经常使用到,但以防万一。
double const KbToGbFactor = 1d / 1024 /1024;
double gb = kb * KbToGbFactor;
我需要将第三方组件字面量大小(例如“0字节”,“1.1 MB”)转换为通用的字节大小,所以我这样使用:
private static long UnformatBytes(string sizeInWords)
{
if(string.IsNullOrWhiteSpace(sizeInWords))
return -1;
string size = sizeInWords.Split(' ').FirstOrDefault();
double result;
if (string.IsNullOrWhiteSpace(size) || !double.TryParse(size, out result))
{
Debugger.Break();
return -1;
}
int pow;
if (sizeInWords.IndexOf("byte", StringComparison.OrdinalIgnoreCase) > -1)
pow = 0;
else if (sizeInWords.IndexOf("kb", StringComparison.OrdinalIgnoreCase) > -1)
pow = 1;
else if (sizeInWords.IndexOf("mb", StringComparison.OrdinalIgnoreCase) > -1)
pow = 2;
else if (sizeInWords.IndexOf("gb", StringComparison.OrdinalIgnoreCase) > -1)
pow = 3;
else if (sizeInWords.IndexOf("tb", StringComparison.OrdinalIgnoreCase) > -1)
pow = 4;
else
return -1;
return System.Convert.ToInt64((result * Math.Pow(1024, pow)));
}
decimal GB = KB / 1024 / 1024;
改为decimal GB = KB / 1024 / 1024;
更好一些..." - sth