Skip to content

Instantly share code, notes, and snippets.

@tmori3y2
Last active November 28, 2016 22:43
Show Gist options
  • Save tmori3y2/9d4e1579b7b6e9ee0bfd2bd968c3aa83 to your computer and use it in GitHub Desktop.
Save tmori3y2/9d4e1579b7b6e9ee0bfd2bd968c3aa83 to your computer and use it in GitHub Desktop.
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