Last active
November 28, 2016 22:43
-
-
Save tmori3y2/9d4e1579b7b6e9ee0bfd2bd968c3aa83 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
public static class Program | |
{ | |
public static void Main() | |
{ | |
"# Zero".Dump(); | |
(0.0f).ToBinaryStringDump("Zero"); | |
(-0.0f).ToBinaryStringDump("-Zero"); | |
new UnionFloat { DWord = 0x80000000 }.Dump("-Zero (0x80000000)"); | |
string.Empty.Dump(); | |
"# Normalized number furthest from zero".Dump(); | |
(float.MinValue).ToBinaryStringDump("MinValue"); | |
(float.MaxValue).ToBinaryStringDump("MaxValue"); | |
Pow2.SubstToBinaryStringDump(128, 104); | |
string.Empty.Dump(); | |
"# Normalized number closest to zero".Dump(); | |
Pow2.Pow2ToBinaryStringDump(-126); | |
string.Empty.Dump(); | |
"# Normalized number near to 2^(24)".Dump(); | |
for (int i = -3; i < 5; i++) | |
{ | |
Pow2.Pow2ToBinaryStringDump(24, i); | |
} | |
string.Empty.Dump(); | |
"# Decimal convert issue of normalized number near to 2^(24)".Dump(); | |
for (int i = -3; i <= 0; i++) | |
{ | |
string title = "2^(24) " + string.Format("{0:+ #;- #;#}", i); | |
new UnionFloat { Value = (float)((int)Math.Pow(2, 24) + i) }.DumpDecimal(title); | |
} | |
string.Empty.Dump(); | |
"# Normalized number near to 2^(25)".Dump(); | |
for (int i = -4; i < 9; i++) | |
{ | |
Pow2.Pow2ToBinaryStringDump(25, i); | |
} | |
string.Empty.Dump(); | |
"# Normalized number less than 1.0".Dump(); | |
float[] TestSources = new float[] | |
{ | |
0.001f, | |
0.01f, | |
0.1f, | |
0.2f, | |
0.3f, | |
0.4f, | |
0.5f, | |
0.6f, | |
0.7f, | |
0.8f, | |
0.9f | |
}; | |
foreach (var value in TestSources) | |
{ | |
value.ToBinaryStringFormat("G7"); | |
} | |
string.Empty.Dump(); | |
"# Normalized number fraction part loss".Dump(); | |
float[] TestSources2 = new float[] | |
{ | |
0.001f, | |
1.001f, | |
10.001f, | |
100.001f, | |
1000.001f, | |
10000.001f, | |
100000.001f, | |
1000000.001f, | |
}; | |
foreach (var value in TestSources2) | |
{ | |
value.ToBinaryStringFormatEx("G7"); | |
} | |
(10000000.001f).ToBinaryStringFormatEx("G8"); | |
string.Empty.Dump(); | |
"# Denormalized Number".Dump(); | |
(float.Epsilon).ToBinaryStringDump("Epsilon = 2^(-149)"); | |
Pow2.Pow2ToBinaryStringDump(-127); | |
Pow2.SubstToBinaryStringDump(-126, -149); | |
string.Empty.Dump(); | |
"# Machine Epsilon".Dump(); | |
Pow2.AddToBinaryStringDump(0, -23); | |
Pow2.Pow2ToBinaryStringDump(0); | |
Pow2.Pow2ToBinaryStringDump(-23); | |
string.Empty.Dump(); | |
"# Infinity".Dump(); | |
(float.NegativeInfinity).ToBinaryStringDump("-Infinity"); | |
(float.PositiveInfinity).ToBinaryStringDump("+Infinity"); | |
unchecked(1.0f / 0.0f).ToBinaryStringDump("1.0 / 0.0"); | |
string.Empty.Dump(); | |
"# NaN".Dump(); | |
(float.NaN).ToBinaryStringDump("NaN"); | |
new UnionFloat { DWord = 0xFFFFFFFF }.Dump("NaN (0xFFFFFFFF)"); | |
new UnionFloat { DWord = 0x7FFFFFFF }.Dump("NaN (0x7FFFFFFF)"); | |
string.Empty.Dump(); | |
"# Hex String".Dump(); | |
(0.0f).HexStringDump(); | |
(0.1f).HexStringDump(); | |
(0.5f).HexStringDump(); | |
(1.0f).HexStringDump(); | |
(2.0f).HexStringDump(); | |
(3.0f).HexStringDump(); | |
(4.0f).HexStringDump(); | |
string.Empty.Dump(); | |
} | |
public static void Dump(this string value) | |
{ | |
Console.WriteLine(value); | |
} | |
} | |
public static class Pow2 | |
{ | |
public static double ToPow2(int power) | |
{ | |
return Math.Pow(2, power); | |
} | |
public static string ToTitle(int power) | |
{ | |
return string.Format("2^({0})", power); | |
} | |
public static string ToTitle(int power, int additional) | |
{ | |
return string.Format("2^({0}) {1:+ #;- #;#}", power, additional); | |
} | |
public static void Pow2ToBinaryStringDump(int power) | |
{ | |
((float)ToPow2(power)).ToBinaryStringDump(ToTitle(power)); | |
} | |
public static void Pow2ToBinaryStringDump(int power, int additional) | |
{ | |
((float)ToPow2(power) + additional).ToBinaryStringDump(ToTitle(power, additional)); | |
} | |
public static void SubstToBinaryStringDump(int power, int power2) | |
{ | |
var pow = ToPow2(power); | |
var pow2 = ToPow2(power2); | |
string title = string.Format("{0} - {1}", ToTitle(power), ToTitle(power2)); | |
((float)(pow - pow2)).ToBinaryStringDump(title); | |
} | |
public static void AddToBinaryStringDump(int power, int power2) | |
{ | |
var pow = ToPow2(power); | |
var pow2 = ToPow2(power2); | |
string title = string.Format("{0} + {1}", ToTitle(power), ToTitle(power2)); | |
((float)(pow + pow2)).ToBinaryStringDump(title); | |
} | |
} | |
[StructLayout(LayoutKind.Explicit)] | |
public struct UnionFloat | |
{ | |
[FieldOffset(0)] | |
public float Value; | |
[FieldOffset(0)] | |
public uint DWord; | |
public byte Sign { get { return unchecked((byte)(DWord >> 31)); } } | |
public byte ExponentBits { get { return unchecked((byte)(DWord << 1 >> 24)); } } | |
public uint SignificantBits { get { return unchecked((uint)(DWord << 9 >> 9)); } } | |
public string BinaryString { get { return DWord.ToBinaryString(); } } | |
public string BinaryPattern { get { return BinaryString.SetSeparator("_", new int[] { 23, 31 }); } } | |
public int Exponent2 | |
{ | |
get | |
{ | |
return (ExponentBits - 127); | |
} | |
} | |
public int Exponent10 | |
{ | |
get | |
{ | |
double e10 = Math.Log10(Math.Abs(Value)); | |
return (Exponent2 > 0) ? (int)Math.Ceiling((float)e10) : (int)Math.Floor((float)e10); | |
} | |
} | |
public void Dump(string title) | |
{ | |
string binary = string.Empty; | |
uint significantBits = SignificantBits; | |
int e = Exponent2; | |
int e10 = Exponent10; | |
switch(ExponentBits) | |
{ | |
case 0x00: | |
binary += significantBits.ToBinaryString(24).SetSeparator(".", new int[] { 23 }); | |
if (significantBits != 0) | |
{ | |
string formatString = (Sign == 0) ? "{0, -20}: {1} = (-1)^{2} * 2^(-126) * {3} = {4, -10:E8}" : | |
"{0, -20}: {1} = (-1)^{2} * 2^(-126) * {3} = {4, -10:E8}"; | |
string.Format(formatString, title, BinaryPattern, Sign, binary, Value).Dump(); | |
} | |
else | |
{ | |
string formatString = "{0, -20}: {1} = (-1)^{2} * 2^(-126) * {3} = {4, -10:E8}"; | |
string.Format(formatString, title, BinaryPattern, Sign, binary, Value).Dump(); | |
} | |
break; | |
case 0xFF: | |
string.Format("{0, -20}: {1} = {2}", title, BinaryPattern, Value).Dump(); | |
break; | |
default: | |
binary += (significantBits | 0x800000).ToBinaryString(24).SetSeparator(".", new int[] { 23 }); | |
if (-7 <= e10 && e10 < 0) | |
{ | |
string formattedValue = string.Format(string.Concat("{0:G", 8 - e10, "}"), Value); | |
string formatString = (Sign == 0) ? "{0, -20}: {1} = (-1)^{2} * 2^({3, 4}) * {4} = {5}" : | |
"{0, -20}: {1} = (-1)^{2} * 2^({3, 4}) * {4} = {5}"; | |
string.Format(formatString, title, BinaryPattern, Sign, e, binary, formattedValue).Dump(); | |
} | |
else if (0 <= e10 && e10 < 9) | |
{ | |
string formattedValue = string.Format(string.Concat("{0:G", e10, "}"), Value); | |
string formatString = (Sign == 0) ? "{0, -20}: {1} = (-1)^{2} * 2^({3, 4}) * {4} = {5}" : | |
"{0, -20}: {1} = (-1)^{2} * 2^({3, 4}) * {4} = {5}"; | |
string.Format(formatString, title, BinaryPattern, Sign, e, binary, formattedValue).Dump(); | |
} | |
else | |
{ | |
string formatString = "{0, -20}: {1} = (-1)^{2} * 2^({3, 4}) * {4} = {5, 16:E8}"; | |
string.Format(formatString, title, BinaryPattern, Sign, e, binary, Value).Dump(); | |
} | |
break; | |
} | |
} | |
public void DumpEx(string title) | |
{ | |
string binary = string.Empty; | |
uint significantBits = SignificantBits; | |
int e = Exponent2; | |
int e10 = Exponent10; | |
switch(ExponentBits) | |
{ | |
case 0x00: | |
case 0xFF: | |
Dump(title); | |
break; | |
default: | |
if (e < 0) | |
{ | |
binary += (significantBits | 0x800000).ToBinaryString(24 - e).SetSeparator(".", new int[] { 23 - e }); | |
string formatString = (Sign == 0) ? "{0, -20}: {1} = {2, -26} = {3, -20:G20}" : | |
"{0, -20}: {1} = {2, -26} = {3, -20:G20}"; | |
string.Format(formatString, title, BinaryPattern, binary, Value).Dump(); | |
} | |
else if (e < 23) | |
{ | |
binary += (significantBits | 0x800000).ToBinaryString(24).SetSeparator(".", new int[] { 23 - e }); | |
string formatString = (Sign == 0) ? "{0, -20}: {1} = {2, -26} = {3, -20:G20}" : | |
"{0, -20}: {1} = {2, -26} = {3, -20:G20}"; | |
string.Format(formatString, title, BinaryPattern, binary, Value).Dump(); | |
} | |
else if (23 <= e && e <= 25) | |
{ | |
binary += (significantBits | 0x800000).ToBinaryString(24); | |
string formatString = (Sign == 0) ? "{0, -20}: {1} = {2, -26} = {3, -8:G8}" : | |
"{0, -20}: {1} = {2, -26} = {3, -8:G8}"; | |
string.Format(formatString, title, BinaryPattern, binary, Value).Dump(); | |
} | |
else | |
{ | |
Dump(title); | |
} | |
break; | |
} | |
} | |
public void DumpDecimal(string title) | |
{ | |
Console.WriteLine("{0, -20}: To Decimal: {1:G28}, To Double: {2:G28}, To Int32: {3:G28}", title, Convert.ToDecimal(Value), Convert.ToDouble(Value), Convert.ToInt32(Value)); | |
} | |
} | |
public static class BinaryStringHelper | |
{ | |
public static string ToBinaryString(this uint value) | |
{ | |
return unchecked(((int)value).ToBinaryString()); | |
} | |
public static string ToBinaryString(this uint value, int digits) | |
{ | |
return unchecked(((int)value).ToBinaryString(digits)); | |
} | |
public static string ToBinaryString(this int value) | |
{ | |
return Convert.ToString(value, 2).SetPadding(32); | |
} | |
public static string ToBinaryString(this int value, int digits) | |
{ | |
return Convert.ToString(value, 2).SetPadding(digits); | |
} | |
public static string ToBinaryString(this float value) | |
{ | |
return new UnionFloat { Value = value }.DWord.ToBinaryString(); | |
} | |
public static string ToBinaryString(this float value, int digits) | |
{ | |
return new UnionFloat { Value = value }.DWord.ToBinaryString(digits); | |
} | |
public static void ToBinaryStringDump(this float value, string title) | |
{ | |
new UnionFloat { Value = value }.Dump(title); | |
} | |
public static void ToBinaryStringDumpEx(this float value, string title) | |
{ | |
new UnionFloat { Value = value }.DumpEx(title); | |
} | |
public static void ToBinaryStringFormat(this float value, string format) | |
{ | |
value.ToBinaryStringDump(value.ToString(format)); | |
} | |
public static void ToBinaryStringFormatEx(this float value, string format) | |
{ | |
value.ToBinaryStringDumpEx(value.ToString(format)); | |
} | |
public static string SetPadding(this string binaryString, int digits) | |
{ | |
// adds lost digits. | |
int length = binaryString.Length; | |
//if (digits > length) return binaryString.Insert(0, new string('0', digits - length)); | |
if (digits > 0) return binaryString.PadLeft(digits, '0'); | |
return binaryString; | |
} | |
public static string SetSeparator(this string binaryString, string separator, int[] digitsList) | |
{ | |
// adds lost digits. | |
var result = binaryString; | |
int length = result.Length; | |
if (digitsList.Length > 0) | |
{ | |
// digitsList: from lsb to msb | |
foreach (var digits in digitsList) | |
{ | |
var position = length - digits; | |
if (position > 0) result = result.Insert(position, separator); | |
} | |
} | |
return result; | |
} | |
} | |
public static class HexStringHelper | |
{ | |
public static string ToHexString(this float value) | |
{ | |
return BitConverter.ToString(BitConverter.GetBytes(value)); | |
} | |
public static void HexStringDump(this float value) | |
{ | |
Console.WriteLine("{0, -20:F8}: {1}", value, value.ToHexString()); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment