我正在重構一些舊的代碼,並遇到以下代碼行將字節轉換爲GB。在C#中將字節轉換爲GB?
decimal GB = KB/1024/1024/1024;
有沒有更好的方法來重構下面的一段代碼?
更新
我的意思是說字節千兆字節。我給了錯誤的信息。
我正在重構一些舊的代碼,並遇到以下代碼行將字節轉換爲GB。在C#中將字節轉換爲GB?
decimal GB = KB/1024/1024/1024;
有沒有更好的方法來重構下面的一段代碼?
更新
我的意思是說字節千兆字節。我給了錯誤的信息。
如果準確的精度並不重要,使用雙:
double gb = kb/1048576D
與帕維爾在這裏同意 - 有沒有真正的任何需要重構的代碼......其實,如果這是在你的代碼庫的最大問題,我想你可能會坐在有史以來最好的軟件上。
就我個人而言,我會這樣寫:decimal GB = KB/(1024 * 1024);
,但確實沒有必要重寫代碼。
原始代碼簡潔,易於閱讀,並具有合理的變量名稱,自我記錄;我不會改變它。
如果你絕對必須重構,你可以創建上的數字類型的一組擴展方法:
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();
但是,除非你的代碼做幾乎沒有,但字節轉換爲千字節等等,這一切真的會做的是混亂了Intellisense沒有真正的收益。
那麼,公式是錯誤的(在千兆字節中只有大約一百萬千字節,而不是千萬字節),但除此之外,沒關係。任何以前使用這些號碼的人都會知道它的含義。
我會注意的一件事(我不知道這是否是C#的問題)是如果x
不是基本類型,編譯器可能無法優化x/1024/1024
。使用C和整數,編譯器可以很容易地將其轉換爲「盲目快速移位 - 右乘20位」指令。
如果十進制是一個類而不是基本類型,編譯器可能不得不做兩個除法操作。這是否對速度有任何實際影響(或者甚至是否真的發生)都超出了我的知識領域。
我會考慮改變的一件事是實際的變量名稱。它對編譯代碼並沒有真正的區別,但我更喜歡較長的變量名稱而不是縮寫,所以我會選擇kiloBytes/gigaBytes
或類似的東西。根據您的編碼標準,KB/GB
太容易與常量混淆。
decimal是一個內置的類型,而不是類。但它也不支持bitshifts,即使它們有意義。也許編譯器可以在這種情況下使用它們,即使程序員不能。 – 2014-08-20 03:15:13
爲了確保預編譯計算除數:
decimal GB = KB/(1024 * 1024);
請注意,您在實際計算吉布(gibibyte),而不是GB(千兆字節)。如果你真的想計算國標,那將是:
decimal GB = KB/(1000 * 1000);
理論上,這是更快的(預計算常數做乘法而不是除法)。它可能沒有足夠重要,但以防萬一。
double const KbToGbFactor = 1d/1024 /1024;
double gb = kb * KbToGbFactor;
我非常肯定這將在程序編譯時進行優化。不管你是否想要一個const在這裏,這更多的是品味的問題。 – Spoike 2010-01-17 22:29:37
我不太確定 - http://blogs.msdn.com/ericlippert/archive/2009/06/11/what-does-the-optimize-switch-do.aspx – 2010-01-18 10:57:33
我喜歡這個答案的「清晰度」 (在我看來),但不是用於「優化」。 Uhg :-) – 2010-10-21 06:21:19
我在這裏開發了這個方法,工作到結核病。
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]);
}
/// <summary>
/// Function to convert the given bytes to either Kilobyte, Megabyte, or Gigabyte
/// </summary>
/// <param name="bytes">Double -> Total bytes to be converted</param>
/// <param name="type">String -> Type of conversion to perform</param>
/// <returns>Int32 -> Converted bytes</returns>
/// <remarks></remarks>
public static double ConvertSize(double bytes, string type)
{
try
{
const int CONVERSION_VALUE = 1024;
//determine what conversion they want
switch (type)
{
case "BY":
//convert to bytes (default)
return bytes;
case "KB":
//convert to kilobytes
return (bytes/CONVERSION_VALUE);
case "MB":
//convert to megabytes
return (bytes/CalculateSquare(CONVERSION_VALUE));
case "GB":
//convert to gigabytes
return (bytes/CalculateCube(CONVERSION_VALUE));
default:
//default
return bytes;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return 0;
}
}
/// <summary>
/// Function to calculate the square of the provided number
/// </summary>
/// <param name="number">Int32 -> Number to be squared</param>
/// <returns>Double -> THe provided number squared</returns>
/// <remarks></remarks>
public static double CalculateSquare(Int32 number)
{
return Math.Pow(number, 2);
}
/// <summary>
/// Function to calculate the cube of the provided number
/// </summary>
/// <param name="number">Int32 -> Number to be cubed</param>
/// <returns>Double -> THe provided number cubed</returns>
/// <remarks></remarks>
public static double CalculateCube(Int32 number)
{
return Math.Pow(number, 3);
}
//Sample Useage
String Size = "File is " + ConvertSize(250222,"MB") + " Megabytes in size"
我需要它周圍的其他方法,從在詞語第三方組件文字大小轉換(例如,「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)));
}
我寫了一個小工具類執行單位之間的轉換,心連心..
#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;
}
}
public static string BytesToString(this long bytes, string format = "#,##0.00") {
var unitstr = new string[] { "B", "KB", "MB", "GB", "TB" };
var bytesd = Convert.ToDouble(bytes);
var unit = 0;
while (bytesd/1024D > 1 && unit < unitstr.Length) {
unit++; bytesd /= 1024D;
}
return string.Format("{0:" + format + "}{1}", bytesd, unitstr[unit]);
}
#region AutoFileSize
public string AutoFileSize(long number)
{
double tmp = number;
string suffix = " B ";
if (tmp > 1024) { tmp = tmp/1024; suffix = " KB"; }
if (tmp > 1024) { tmp = tmp/1024; suffix = " MB"; }
if (tmp > 1024) { tmp = tmp/1024; suffix = " GB"; }
if (tmp > 1024) { tmp = tmp/1024; suffix = " TB"; }
return tmp.ToString("n") + suffix;
}
#endregion
long number = (long)fu.PostedFile.ContentLength;
這是很好的一個小改進JLopez的回答(請投票給他,不是我)。 在這裏,你可以選擇或不單位指示和公斤單元被寫入與小寫字母「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)}";
}
'小數GB = KB/1024/1024;'將要更好...... – sth 2009-08-07 00:31:00
除了額外的劃分之外,代碼的寫法沒有問題;它的意圖非常清楚,沒有不必要的冗長,並且沒有性能問題。你爲什麼要重構它? – 2009-08-07 00:35:52
我認爲這很好,但我可能會GB =字節* 1E-9; – kenny 2010-01-17 22:28:17