计算机采用二进制补码【Complement】的格式来表示十进制整数,无论正整数、0、负整数都是采用二进制补码的方式来存储数据。
基本概念
原码:
一个正数,按照其本身大小转换成的二进制数,称为原码
一个负数,按照其绝对值大小转换成的二进制数,最高位补1,称为原码
反码:
正数的反码与原码相同
负数的反码为对该数的原码除符号位【最高位】外各位取反(0变1,1变0,符号位为1不变)
补码:
正数的补码与原码相同
负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.即对负数的补码为对该数的反码的最后一位加1
综述
正数的补码为本身,0的补码为0,负数的补码【将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1】,对于C#来说,使用一个强转即可。如下代码:
int x=-123;
byte twosComplement=(byte)x;
下面使用WindowsForm应用程序测试整数的二进制原码、反码、补码
负数的新建WinForms应用程序BinaryDemo,将默认的Form1重命名为FormBinary,
窗体FormBinary设计如下:
FormBinary源程序如下:
(忽略设计器自动生成的代码)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BinaryDemo
{
public partial class FormBinary : Form
{
public FormBinary()
{
InitializeComponent();
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("八位SByte", 8);
dict.Add("十六位Int16", 16);
dict.Add("三十二位Int32", 32);
cboBase.DropDownStyle = ComboBoxStyle.DropDownList;
cboBase.DataSource = dict.ToList();
cboBase.DisplayMember = "Key";
cboBase.ValueMember = "Value";
cboBase.SelectedIndex = 2;//默认选中32bits
}
private void FormBinary_Load(object sender, EventArgs e)
{
/* 计算机采用二进制补码【Complement】的格式来表示十进制整数
* 原码:
* 一个正数,按照其本身大小转换成的二进制数,称为原码
* 一个负数,按照其绝对值大小转换成的二进制数,最高位补1,称为原码
*
* 反码:
* 正数的反码与原码相同
* 负数的反码为对该数的原码除符号位外各位取反
*
* 补码:
* 正数的补码与原码相同
* 负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.即对负数的补码为对该数的反码的最后一位加1
*/
}
/// <summary>
/// 验证输入
/// </summary>
/// <returns></returns>
private bool CheckInput()
{
if (txtSourceNumber.Text.Trim().Length == 0)
{
txtSourceNumber.Focus();
MessageBox.Show("源整数不能为空", "出错");
return false;
}
int fromBase = Convert.ToInt32(cboBase.SelectedValue);
switch (fromBase)
{
case 8:
if (!sbyte.TryParse(txtSourceNumber.Text, out sbyte result1))
{
txtSourceNumber.Focus();
MessageBox.Show("请输入[-128,127]之间的整数", "出错");
return false;
}
break;
case 16:
if (!short.TryParse(txtSourceNumber.Text, out short result2))
{
txtSourceNumber.Focus();
MessageBox.Show("请输入[-32768,32767]之间的整数", "出错");
return false;
}
break;
case 32:
if (!int.TryParse(txtSourceNumber.Text, out int result3))
{
txtSourceNumber.Focus();
MessageBox.Show($"请输入[{int.MinValue},{int.MaxValue}]之间的整数", "出错");
return false;
}
break;
}
return true;
}
private void btnGet_Click(object sender, EventArgs e)
{
if (!CheckInput())
{
return;
}
int fromBase = Convert.ToInt32(cboBase.SelectedValue);
long result = 0;
switch (fromBase)
{
case 8:
result = sbyte.Parse(txtSourceNumber.Text);
break;
case 16:
result = short.Parse(txtSourceNumber.Text);
break;
case 32:
result = int.Parse(txtSourceNumber.Text);
break;
}
txtBinary.Text = Convert.ToString((int)result, 2).PadLeft(32, '0');
DisplayBinaryWhenEightBit(txtBinary);
if (Math.Sign(result) < 0) //是否是负数
{
//如果是负数,先获取绝对值,然后最高位补1
switch (fromBase)
{
case 8:
GetNegativeOriginalBinary(fromBase, (sbyte)result);
break;
case 16:
GetNegativeOriginalBinary(fromBase, (short)result);
break;
case 32:
GetNegativeOriginalBinary(fromBase, (int)result);
break;
}
//GetNegativeOriginalBinary(fromBase, result);
//负数的反码为对该数的原码除符号位外各位取反
string sAnticode = "1";
for (int i = 1; i < fromBase; i++)
{
sAnticode += (txtOriginalBinary.Text[i] == '0' ? "1" : "0");
}
txtAnticodeBinary.Text = sAnticode;
//负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1.即对负数的补码为对该数的反码的最后一位加1
txtComplementBinary.Text = Convert.ToString(Convert.ToInt64(sAnticode, 2) + 1, 2);
}
else
{
//如果是正数,最高位补零
txtOriginalBinary.Text = "0" + Convert.ToString(result, 2).PadLeft(fromBase - 1, '0');
txtAnticodeBinary.Text = txtOriginalBinary.Text;
txtComplementBinary.Text = txtOriginalBinary.Text;
}
txtOriginal.Text = Convert.ToInt64(txtOriginalBinary.Text, 2).ToString();
txtAnticode.Text = Convert.ToInt64(txtAnticodeBinary.Text, 2).ToString();
txtComplement.Text = Convert.ToInt64(txtComplementBinary.Text, 2).ToString();
DisplayBinaryWhenEightBit(txtOriginalBinary);
DisplayBinaryWhenEightBit(txtAnticodeBinary);
DisplayBinaryWhenEightBit(txtComplementBinary);
}
/// <summary>
/// 获取负数的原码
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fromBase"></param>
/// <param name="resultText"></param>
private void GetNegativeOriginalBinary<T>(int fromBase, T resultText) where T : struct, IComparable
{
if (fromBase == 8)
{
sbyte result = (sbyte)(object)resultText;
//如果是负数,先获取绝对值,然后最高位补1
if (result == sbyte.MinValue)
{
byte processValue = (byte)result;//直接就是8位
txtOriginalBinary.Text = Convert.ToString(processValue, 2);
}
else
{
sbyte absValue = Math.Abs(result);
txtOriginalBinary.Text = "1" + Convert.ToString(absValue, 2).PadLeft(fromBase - 1, '0');
}
}
else if (fromBase == 16)
{
short result = (short)(object)resultText;
//如果是负数,先获取绝对值,然后最高位补1
if (result == short.MinValue)
{
ushort processValue = (ushort)result;//直接就是16位
txtOriginalBinary.Text = Convert.ToString(processValue, 2);
}
else
{
short absValue = Math.Abs(result);
txtOriginalBinary.Text = "1" + Convert.ToString(absValue, 2).PadLeft(fromBase - 1, '0');
}
}
else if (fromBase == 32)
{
int result = (int)(object)resultText;
//如果是负数,先获取绝对值,然后最高位补1
if (result == int.MinValue)
{
uint processValue = (uint)result;//直接就是32位
txtOriginalBinary.Text = Convert.ToString(processValue, 2);
}
else
{
int absValue = Math.Abs(result);
txtOriginalBinary.Text = "1" + Convert.ToString(absValue, 2).PadLeft(fromBase - 1, '0');
}
}
}
/// <summary>
/// 将文本框的二进制字符串每隔8位就使用空格 间隔开
/// </summary>
/// <param name="textBox"></param>
private void DisplayBinaryWhenEightBit(TextBox textBox)
{
int pageSize = (textBox.Text.Length + 7) / 8;
string[] splitArray = new string[pageSize];
for (int i = 0; i < pageSize; i++)
{
if (i + 1 == pageSize)
{
splitArray[i] = textBox.Text.Substring(8 * i);
}
else
{
splitArray[i] = textBox.Text.Substring(8 * i, 8);
}
}
//使用空格拼接
textBox.Text = string.Join("\x20\u0020", splitArray);
}
}
}
程序运行如图: