-
2016-11-19 23:08:51模2运算是一种二进制算法,CRC校验技术中的核心部分,因此,我们在分析CRC算法之前,必须掌握模2运算的规则。 与四则运算相同,模2运算也包括模2加、模2减、模2乘、模2除四种二进制运算。而且,模2运算也使用与四则运算相同的运算符,即“+”表示模2加,“-”表示模2减,“×”或“·”表示模2乘,“÷”或“/”表示模2除。与四则运算不同的是模2运算不考虑进位和借位,即模2加法是不带进位的二进制加法运算,模2减法是不带借位的二进制减法运算。这样,两个二进制位相运算时,这两个位的值就能确定运算结果,不受前一次运算的影响,也不对下一次造成影响。
①模2加法运算定义为:
0+0=0 0+1=1 1+0=1 1+1=0
例如0101+0011=0110,列竖式计算:
0 1 0 1
+0 0 1 1
──────
0 1 1 0
②模2减法运算定义为:
0-0=0 0-1=1 1-0=1 1-1=0
例如0110-0011=0101,列竖式计算:
0 1 1 0
- 0 0 1 1
──────
0 1 0 1
③模2乘法运算定义为:
0×0=0 0×1=0 1×0=0 1×1=1
多位二进制模2乘法类似于普通意义上的多位二进制乘法,不同之处在于后者累加中间结果(或称部分积)时采用带进位的加法,而模2乘法对中间结果的处理方式采用的是模2加法。例如1011×101=100111,列竖式计算:
1 0 1 1
× 1 0 1
──────
1 0 1 1
0 0 0 0
+1 0 1 1
────────
1 0 0 1 1 1
④模2除法运算定义为:
0÷1=0 1÷1=1
多位二进制模2除法也类似于普通意义上的多位二进制除法,但是在如何确定商的问题上两者采用不同的规则。后者按带借位的二进制减法,根 据余数减除数够减与否确定商1还是商0,若够减则商1,否则商0。多位模2除法采用模2减法,不带借位的二进制减法,因此考虑余数够减除数与否是没有意义 的。实际上,在CRC运算中,总能保证除数的首位为1,则模2除法运算的商是由余数首位与除数首位的模2除法运算结果确定。因为除数首位总是1,按照模2 除法运算法则,那么余数首位是1就商1,是0就商0。例如1100100÷1011=1110……110,列竖式计算:
1 1 1 0
────────
1 0 1 1〕1 1 0 0 1 0 0
- 1 0 1 1
──────
1 1 1 1
- 1 0 1 1
──────
1 0 0 0
- 1 0 1 1
──────
0 1 1 0
- 0 0 0 0
──────
1 1 0
更多相关内容 -
04-C语言进制和位运算
2021-05-19 12:10:18进制是一种计数的方式,数值的表示形式常见的进制十进制、二进制、八进制、十六进制进制书写的格式和规律十进制 0、1、2、3、4、5、6、7、8、9 逢十进一二进制 0、1 逢二进一在C语言中, 如果想用二进制表示某个数, ...进制基本概念
什么是进制?
进制是一种计数的方式,数值的表示形式
常见的进制
十进制、二进制、八进制、十六进制
进制书写的格式和规律
十进制 0、1、2、3、4、5、6、7、8、9 逢十进一
二进制 0、1 逢二进一
在C语言中, 如果想用二进制表示某个数, 前面需要加上0b;
八进制 0、1、2、3、4、5、6、7 逢八进一
在C语言中, 如果想用八进制表示某个数, 前面需要加上0;
十六进制 0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F 逢十六进一
在C语言中, 如果想用十六进制表示某个数, 前面需要加上0x;
注意点:
%i %d代表以十进制输出整数
0x 和 0X写法 一样, 0b和0B写法也一样
// 12的不同进制的表达
// 用十进制来表示
int num1 = 12;
printf("num1 = %i\n", num1);
// 用十六进制来表示
int num2 = = 0xc;
printf("num2 = %i\n", num2);
// 用八进制来表示
int num3 = 014;
printf("num3 = %i\n", num3);
// 用二进制来表示
int num4 = 0b1100;
printf("num4 = %i\n", num4);
// 不同进制的输出
int num = 12;
// 以十进制输出
printf("%i\n", num);
// 以八进制输出
printf("%o\n", num);
// 以十六进制输出
printf("%x\n", num);
//二进制
void printBinary(char value){
}
进制转换
十进制转二进制
除2取余, 余数倒序; 得到的序列就是二进制表示形式
/*
* 求12的二进制数
* 12
* 2
* ----
* 6 0
* 2
* ----
* 3 0
* 2
* ----
* 1 1
* 2
* ----
* 0 1
*
* 12 --> 1100
*/
二进制转十进制
规则: 系数 * 基数^(索引)
系数:就是每一位对应的值就是系数;
基数: 如果是二进制转到十进制,那么2就是基数
-如果是从八进制转换到十进制, 那么八就是基数
索引:从最低位以0开始,依次递增;
/*
1*2^3 + 1*2^2 + 0*2^1 + 0*2^0
1 1 0 0
==> 8 + 4 + 0 + 0 = 12
*/
/*
* 二进制快速转换十进制
* 64 32 16 8 4 2 1
* 1 1 1 1 1 1 1
*/
十进制转换八进制
规则: 除8取余,余数倒数
/* 十进制24转换为八进制
*
* 24
* 8
* ---
* 3 0
* 8
* ---
* 0 3
*
* 24 --> 30
*/
二进制转换为八进制
必须知道:在八进制中最大的数字是7
1.可以使用系数 * 基数^(索引) 将二进制转换为8进制
2.二进制在转换为8进制的时候,把三个二进制数看做一个八进制位即可
/*从右至左每3位划分为8进制的1位, 不够前面补0
001 100 100
第0位: 100 等于十进制 4
第1位: 100 等于十进制 4
第2位: 001 等于十进制 1
最终结果: 144就是转换为8进制的值
/*
二进制转换为十六进制
二进制在转换为十六进制的时候,把四个二进制位看做一个十六进制为即可
/*
3 8
0011 1000 ==> 0x38
*/
十进制小数转换为二进制小数
整数部分,直接转换为二进制即可
小数部分,使用"乘2取整,顺序排列"
用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,直到积中的小数部分为零,或者达到所要求的精度为止
然后把取出的整数部分按顺序排列起来, 即是小数部分二进制
最后将整数部分的二进制和小数部分的二进制合并起来, 即是一个二进制小数
例如: 将12.125转换为二进制
// 整数部分(除2取余)
12
/ 2
------
6 // 余0
/ 2
------
3 // 余0
/ 2
------
1 // 余1
/ 2
------
0 // 余1
//12 --> 1100
// 小数部分(乘2取整数积)
0.125
* 2
------
0.25 //0
0.25
* 2
------
0.5 //0
0.5
* 2
------
1.0 //1
0.0
// 0.125 --> 0.001
// 12.8125 --> 1100.001
二进制转换为十进制小数
整数部分按照二进制转十进制即可
小数部分从最高位开始乘以2的负n次方, n从1开始
例如: 将 1100.001转换为十进制
// 整数部分(乘以2的n次方, n从0开始)
0 * 2^0 = 0
0 * 2^1 = 0
1 * 2^2 = 4
1 * 2^3 = 8
// 1100 == 8 + 4 + 0 + 0 == 12
// 小数部分(乘以2的负n次方, n从0开始)
0 * (1/2) = 0
0 * (1/4) = 0
1 * (1/8) = 0.125
// .100 == 0 + 0 + 0.125 == 0.125
// 1100.001 --> 12.125
将0.8125转换为二进制
0.8125
* 2
--------
1.625 // 1
0.625
* 2
--------
1.25 // 1
0.25
* 2
--------
0.5 // 0
* 2
--------
1.0 // 1
0.0
// 0. 8125 --> 0.1101
原码 补码 反码之间的关系
正数的原码 = 补码 = 反码 ; (三码合一);
int 类型在计算机中占用4个字节
1个字节等于8位,所以int类型总共占用32位;
注意点:
在存储正整数的时候,第一个(最高位)是符号位, 0是代表正数, 1代表是负数;
0000 0000 0000 0000 0000 0000 0000 1100
// int num = 12;
负整数的原码, 补码, 反码
// int num = -12;
原码 : 二进制,将最高位变为1;
1000 0000 0000 0000 0000 0000 0000 1100
反码 : 除了符号位以外, 0变1, 1变0;
1000 0000 0000 0000 0000 0000 0000 1100 12的反码
补码 : 反码 + 1
1111 1111 1111 1111 1111 1111 1111 0011 12的反码
+ 0000 0000 0000 0000 0000 0000 0000 0001 +1
----------------------------------------
1111 1111 1111 1111 1111 1111 1111 0100 12的补码
// 注意点: 无论是正整数还是负整数,存储在计算机中都是补码
如果只有原码参与运算会出现什么问题
// 1 - 1; 1 + (-1);
0000 0000 0000 0000 0000 0000 0000 0001 // 1原码
+1000 0000 0000 0000 0000 0000 0000 0001 // -1原码
---------------------------------------
1000 0000 0000 0000 0000 0000 0000 0010 == -2
很明显,上面的运算结果不成立
计算机只能做就加法运算,而且是做补码运算;
/*
* 1 - 1 理解为 1 + (-1)
* 0000 0000 0000 0000 0000 0000 0000 0001 1补码就是原码
*
// 求-1的补码
* 1000 0000 0000 0000 0000 0000 0000 0001 -1源码
* 1111 1111 1111 1111 1111 1111 1111 1110 -1反码
* 0000 0000 0000 0000 0000 0000 0000 0001
* -----------------------------------------
* 1111 1111 1111 1111 1111 1111 1111 1111 -1补码
*
*
* 0000 0000 0000 0000 0000 0000 0000 0001 1补码
* + 1111 1111 1111 1111 1111 1111 1111 1111 -1补码
* -------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 0000 0
*/
/*
* 4 - 6 --> 4 + (-6)
* 0000 0000 0000 0000 0000 0000 0000 0100 4补码
*
* 1000 0000 0000 0000 0000 0000 0000 0110 -6源码
* 1111 1111 1111 1111 1111 1111 1111 1001 -6反码
* 0000 0000 0000 0000 0000 0000 0000 0001
* -------------------------------------------
* 1111 1111 1111 1111 1111 1111 1111 1010 -6补码
*
*
*
* 0000 0000 0000 0000 0000 0000 0000 0100 4补码
* 1111 1111 1111 1111 1111 1111 1111 1010 -6补码
* 1111 1111 1111 1111 1111 1111 1111 1110 补码的结果
*
* 注意点: 当前计算出来的是正确结果的补码, 要想知道正确结果是多少, 需要将补码转换为源码
// 原码 = (补码 - 1)再求其反码
*
* 1111 1111 1111 1111 1111 1111 1111 1110 结果的补码
* 0000 0000 0000 0000 0000 0000 0000 0001 减1
* -------------------------------------------
* 1111 1111 1111 1111 1111 1111 1111 1101 结果的反码
* 1000 0000 0000 0000 0000 0000 0000 0010 结果的源码 -2
*/
/*
0101
+ 0001
-----
0102 --> 0110
0110 --> 0102
- 0001 0001
---------------
0101
*/
位运算符
符号
名称
运算结果
&
按位与
同1为1
|
按位或
有1为1
^
按位异或
不同为1
~
按位取反
0变1,1变0
<<
按位左移
乘以2的n次方
>>
按位右移
除以2的n次方
& 按位与
规则: 两个都是真(1)时,结果才是真(1);
规律:任何一位和1相与,结果还是原来的那一位;
/*
* 9 & 3 = ?
* 0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
* & 0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
* -----------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 0001 // 1
*
* 12 & 8
* 0000 0000 0000 0000 0000 0000 0000 1100 //12的补码
*& 0000 0000 0000 0000 0000 0000 0000 1000 //8的补码
* -----------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 1000 //4
*/
应用: 判断奇数偶数
int num = 4;
// if(1 == (num & 1)){
// printf("%i是奇数\n", num);
// }else{
// printf("%i是偶数\n", num);
// }
if(num & 1){
printf("%i是奇数\n", num);
}else{
printf("%i是偶数\n", num);
}
| 按位或
只要对应的二个二进位有一个为1时,结果位就为1,否则为0
/* 9 | 3 = ?
* 0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
*| 0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
* -----------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 1011 // 11
*/
~ 按位取反
规则:0变1, 1变0 ;
/* ~9 = ?
* 0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
*~1111 1111 1111 1111 1111 1111 1111 0110 // 结果的补码
* 0000 0000 0000 0000 0000 0000 0000 0001
* -------------------------------------------
* 1111 1111 1111 1111 1111 1111 1111 0101 // 结果补码的反码
* 1000 0000 0000 0000 0000 0000 0000 1010 // 结果的源码 -10
*/
^ 按位异或
规则: 相同为0,不同为1;
/* 9 ^ 3 = ?
* 0000 0000 0000 0000 0000 0000 0000 1001 // 9的补码
*^0000 0000 0000 0000 0000 0000 0000 0011 // 3的补码
*-------------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 1010 // 10
*/
规律:
任何两个相同的值异或之后的结果都是0;
任何一个数和0异或之后的结果还是那个数
任何一个数异或另外一个数两次之后,结果还是那个数;
应用场景:简单的加密
int pwd = 123456789;
int res = pwd ^ 998;
printf("加密之前: %i\n", pwd);
printf("加密之后: %i\n", res);
int res2 = res ^ 998;
printf("解密之后: %i\n", res2);
交换两个数的值(按位异或)(任何一个数异或另外一个数两次之后,结果还是那个数;)
/*
* 需求: 交换两个变量的值
*
* int a = 10; int b = 20;
*/
int a = 10;
int b = 20;
printf("交换之前a = %i, b = %i\n", a, b);
// a = a ^ b;
// b = a ^ b; // b = a ^ (b ^ b) = a; b = 10;
// a = a ^ b; // a = (a ^ a) ^ b = b; a = 20;
b = a ^ b;
a = a ^ b; // a = a ^ a ^ b; a = b; a = 20;
b = a ^ b; // b = a ^ b ^ b; b = a; a = 10;
printf("交换之后a = %i, b = %i\n", a, b);
--------------------------------------------------------
// 之前学的
// 重点掌握
// int temp = a;
// a = b;
// b = temp;
// printf("交换之后a = %i, b = %i\n", a, b);
// a = a + b; // a = 10 + 20; a = 30;
// b = a - b; // b = 30 - 20; b = 10;
// a = a - b; // a = 30 - 10; a = 20;
// printf("交换之后a = %i, b = %i\n", a, b);
按位左移 <<
移动规则:从符号位开始整体移动,多余的砍掉,缺少的用零补
计算规律: 一个数左移多少位,就是这个数乘以2的多少次幂
应用场景: 在企业开发中一旦想要某个数乘以2的多少次幂, 就要想到左移
例如: 9 * 2(1) = 18 ; 9 * 2(2) = 36
9 << 1
0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
000 0000 0000 0000 0000 0000 0000 10010 // 9的补码
按位右移 <<
移动规则: 除符号位以外整体右移,多出来的砍掉,缺少的用符号位填充;
计算规则: 一个正数右移多少位,就是这个数除以2的n次幂;
/*
// 9 >> 1
0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
00000 0000 0000 0000 0000 0000 0000 100 --> 4
*/
printf("%i\n", 9 >> 1);
// -9 >> 1
/*
* 1000 0000 0000 0000 0000 0000 0000 1001 // -9源码
* 1111 1111 1111 1111 1111 1111 1111 0110 // -9反码
* 1111 1111 1111 1111 1111 1111 1111 0111 // -9补码
*
0000 0000 0000 0000 0000 0000 0000 0000 // 位置参考
11111 1111 1111 1111 1111 1111 1111 011 // 右移完毕的结果, 补码
0000 0000 0000 0000 0000 0000 0000 0001
11111 1111 1111 1111 1111 1111 1111 010 // 右移完毕的结果, 反码
10000 0000 0000 0000 0000 0000 0000 101 // 右移完毕的结果, 源码
*/
printf("%i\n", -9 >> 1);
变量的内存分析
内存是连续的;
内存地址从大到小;
计算机会从内存地址大的开始分配内存(内存寻址从大到小);
也就是说先定义的变量内存地址大于后定义的变量;
变量的存储原则:
先分配字节地址大内存,然后分配字节地址小的内存(内存寻址是从大到小),
变量的首地址,是变量所占存储空间字节地址(最小的那个地址)
低位保存在地地址字节上,高位保存在高地址字节上;
image
定义变量
定义变量的目的就是为了在内存中开辟一块存储空间;
定义变量时指定数据类型的目的就是为了告诉计算机需要开辟多大的空间
char在内存中占用一个字节,int在内存中占用4个字节,double在内存中占用8字节(一个字节 = 8 位);
sizeof(char); sizeof(int); sizeof(double)
由于计算机只能识别0,1,所以会把十进制转换为二进制
给变量分配内存的时候是从内存地址比较大的开始存储;
char类型内存存储细节
%p 是专门用于输出变量地址的
& 是专门用于取出变量地址;
int num1 = 10;
int num2 = 20;
printf("num1 = %p\n", &num1);
printf("num2 = %i\n", &num2);
char类型基本概念
char是c语言中比较灵活的一种数据类型,称为"字符型"
char类型变量占1个字节存储空间, 共8位;
除单个字符以外,C语言的转移字符也可以利用char类型存储;
字符
意义
\b
退格(BS)当前位置向后回退一个字符
\r
回车(CR),将当前位置移至本行开头
\n
换行(LF),将当前位置移至下一行开头
\t
水平制表(HT),跳到下一个TAB 位置
\0
用于表示字符串的结束标记
\
代表一个反斜线字符 \
"
代表一个双引号字符 "
'
代表一个单引号字符 '
char类型的注意点:
char类型占一个字节,所以只有8位可以存储
ASCII码表中字符对应的ASCII值是从0~127
char类型的取值范围 -2^7 ~ 2^7 // -128 ~ 127
一个中文字符占3字节(unicode表),所有char不可以存储中文
char c = '我'; // 错误写法
除转义字符以外,不支持多个字符
char ch = 'ab'; // 错误写法
char 类型存储字符时会先查找对应的ASCII码值,存储的是ASCII值,所以字符6和数字6存储的内容不同;
char ch1 = '6'; // 存储的是ASCII码 64;
char ch2 = 6 ; // 存储的是数字 6;
类型说明符
类型说明符易班都是用于修饰int 类型所以在使用时可以省略int ;
说明长度的:
short 短整型
long 长整型
long long
char ch;
short int num1;
int num2;
long int num3;
long long int num4;
printf("ch = %i\n", sizeof(ch)); // 1
printf("short = %i\n", sizeof(num1)); // 2
printf("int = %i\n", sizeof(num2)); // 4
printf("long = %i\n", sizeof(num3)); // 4
printf("long long = %i\n", sizeof(num4)); // 8
C语言不看怎么存,只看怎么取;
short num5 = 123;
printf("num5 = %lld\n", num5);
long num6 = 123;
printf("num6 = %lld\n", num6);
long long num7 = 123;
printf("num7 = %lld\n", num7); // 123
short 和long
int占用4个字节(32bit),取值范围是-2^31 ~ 2^31-1;
short占用2个字节(16bit),取值范围是-2^15 ~ 2^15-1
long int 在32位编译器中占用4个字节;
在64位编译器中,long占用8个字节(64bit),取值范围是-2^63 ~ 2^63-1
注意点:
如果存储的数据超出了类型对应的取值范围,那么就会导致存储的数据不对
由于内存非常有限,所以在编写程序的时候,尽量合理的定义变量
short的长度不能大于 int , int的长度不能大于long
char 一定为8位(1个字节),毕竟char是我们变成能用的最小数据类型;
说明符号位的:
signed 有符号型(默认int就是有符号的 默认的,一般用不上);
unsigned 无符号型
不把二进制的第一位当做符号位来使用,
所以只能存储零和正数,不能存储负数
注意点: 如果变量被unsigned修饰了,那么取出的时候必须使用%u,%u就代表用无符号;
对于整数而言,在内存中二进制的第一位就是符号位
如果第一位是0,代表正数;第一位是1,代表负数;
默认情况下所有的int 类型都是有符号的,也就是都会将第一位看做符号位;
-
二进制浮点数以及二进制浮点数算术运算
2021-12-19 12:40:04二进制浮点数以及二进制浮点数算术运算二进制浮点数表示半精度浮点数单精度浮点数双精度浮点数特殊情况浮点数的运算步骤一、对阶二、尾数运算三、结果规格化左规操作右规操作四、 舍入处理五、 溢出判断六、例子二...二进制浮点数以及二进制浮点数算术运算
二进制浮点数表示
阶码(指数)就是指数位存储的值,而偏阶(移码)则不同精度的浮点数的偏阶也各不相同,具体可以查看指数偏差。
B i a s = 2 k − 1 − 1 Bias=2^{k-1}-1 Bias=2k−1−1, 其中k是指数中的位数。半精度浮点数
半精度浮点数 是一种被计算机使用的二进制浮点数据类型。半精度浮点数使用2个字节(16位)来存储。
在IEEE 754-2008中,它被称作binary16。这种数据类型只适合存储对精度要求不高的数字,不适合用来计算。IEEE 754 标准指定了一个 binary16 要有如下的格式:
Sign bit(符号位): 1 bit
Exponent width(指数位宽): 5 bits
Significand precision(尾数精度): 11 bits (有10位被显式存储)按如下顺序排列:
除非指数位全是0,否则就会假定隐藏的起始位是1。因此只有10位尾数在内存中被显示出来,而总精度是11位。据IEEE 754的说法,虽然尾数只有10位,但是尾数精度是11位的(log10(211) ≈ 3.311 十进制数).单精度浮点数
单精度浮点数 格式是一种数据类型,在计算机存储器中占用4个字节(32 bits),利用“浮点”(浮动小数点)的方法,可以表示一个范围很大的数值。
第1位表示正负,中间8位表示指数,后23位储存有效数位(有效数位是24位)。
第一位的正负号0代表正,1代表负。
中间八位共可表示 2 8 = 256 2^8=256 28=256个数,指数可以是二补码;或0到255,0到126代表-127到-1,127代表零,128-255代表1-128。
有效数位最左手边的1并不会储存,因为它一定存在(二进制的第一个有效数字必定是1)。换言之,有效数位是24位,实际储存23位。
s i g n = + 1 sign = +1 sign=+1
e x p o n e n t = ( − 127 ) + 124 = − 3 exponent = (-127)+124=-3 exponent=(−127)+124=−3
f r a c t i o n = 1 + 2 − 2 = 1.25 fraction=1+2^{-2}=1.25 fraction=1+2−2=1.25
v a l u e = ( + 1 ) × 1.25 × 2 − 3 = + 0.15625 value=(+1)\times1.25\times2^{-3}=+0.15625 value=(+1)×1.25×2−3=+0.15625双精度浮点数
双精度浮点数(double)是计算机使用的一种资料类型。比起单精度浮点数,双精度浮点数(double)使用 64 位(8字节) 来存储一个浮点数。 它可以表示二进位制的53位有效数字,其可以表示的数字的绝对值范围为 [ 2 − 1024 , 2 1024 ] [2^{-1024}, 2^{1024}] [2−1024,21024]。
特殊情况
以双精度浮点数为例,说明一些特殊情况
当指数exponent全为0或者全为1时,有特殊含义,有以下四种情况,
1、 e x p o n e n t = 0 , f r a c t i o n = 0 ⇒ ± 0 exponent=0, fraction=0 \Rightarrow \pm0 exponent=0,fraction=0⇒±0
2、 e x p o n e n t = 0 , f r a c t i o n ≠ 0 ⇒ 非 正 规 形 式 的 浮 点 数 exponent=0, fraction\neq0 \Rightarrow 非正规形式的浮点数 exponent=0,fraction=0⇒非正规形式的浮点数
3、 e x p o n e n t = 2047 , f r a c t i o n = 0 ⇒ ± ∞ exponent=2047, fraction=0 \Rightarrow \pm\infty exponent=2047,fraction=0⇒±∞
4、 e x p o n e n t = 2047 , f r a c t i o n ≠ 0 ⇒ N a N exponent=2047, fraction\neq0 \Rightarrow NaN exponent=2047,fraction=0⇒NaN浮点数的运算步骤
浮点数的加减运算一般由以下五个步骤完成:
对阶、尾数运算、规格化、舍入处理、溢出判断
一、对阶
所谓对阶是指将两个进行运算的浮点数的阶码对齐的操作。对阶的目的是为使两个浮点数的尾数能够进行加减运算。因为,当进行 M x ⋅ 2 E x M_x·2^{E_x} Mx⋅2Ex与 M y ⋅ 2 E y M_y·2^{E_y} My⋅2Ey加减运算时,只有使两浮点数的指数值部分相同,才能将相同的指数值作为公因数提出来,然后进行尾数的加减运算。对阶的具体方法是:首先求出两浮点数阶码的差,即 Δ E = E x − E y \Delta E = E_x - E_y ΔE=Ex−Ey,将小阶码加上 Δ E \Delta E ΔE,使之与大阶码相等,同时将小阶码对应的浮点数的尾数右移相应位数,以保证该浮点数的值不变。几点注意:
(1)对阶的原则是小阶对大阶,之所以这样做是因为若大阶对小阶,则尾数的数值部分的高位需移出,而小阶对大阶移出的是尾数的数值部分的低位,这样损失的精度更小。
(2)若 Δ E \Delta E ΔE=0,说明两浮点数的阶码已经相同,无需再做对阶操作了。
(3)采用补码表示的尾数右移时,符号位保持不变。
(4)由于尾数右移时是将最低位移出,会损失一定的精度,为减少误差,可先保留若干移出的位,供以后舍入处理用。
二、尾数运算
尾数运算就是进行完成对阶后的尾数相加减。这里采用的就是我们前面讲过的纯小数的定点数加减运算。
三、结果规格化
在机器中,为保证浮点数表示的唯一性,浮点数在机器中都是以规格化形式存储的。对于IEEE754标准的浮点数来说,就是尾数必须是
1.M
的形式。由于在进行上述两个定点小数的尾数相加减运算后,尾数有可能是非规格化形式,为此必须进行规格化操作。规格化操作包括左规和右规两种情况。
左规操作
将尾数左移,同时阶码减值,直至尾数成为 1. M 1.M 1.M的形式。例如,浮点数 0.0011 ∗ 2 5 0.0011*2^5 0.0011∗25是非规格化的形式,需进行左规操作,将其尾数左移3位,同时阶码减3,就变成 1.1100 ∗ 2 2 1.1100*2^2 1.1100∗22规格化形式了。
右规操作
将尾数右移1位,同时阶码增1,便成为规格化的形式了。要注意的是,右规操作只需将尾数右移一位即可,这种情况出现在尾数的最高位(小数点前一位)运算时出现了进位,使尾数成为 10. x x x x 10.xxxx 10.xxxx或 11. x x x x 11.xxxx 11.xxxx的形式。例如, 10.0011 ∗ 2 5 10.0011*2^5 10.0011∗25右规一位后便成为 1.00011 ∗ 2 6 1.00011*2^6 1.00011∗26的规格化形式了。
四、 舍入处理
浮点运算在对阶或右规时,尾数需要右移,被右移出去的位会被丢掉,从而造成运算结果精度的损失。为了减少这种精度损失,可以将一定位数的移出位先保留起来,称为保护位,在规格化后用于舍入处理。
IEEE754标准列出了四种可选的舍入处理方法:
(1)就近舍入(round to nearest)这是标准列出的默认舍入方式,其含义相当于我们日常所说的“四舍五入”。例如,对于32位单精度浮点数来说,若超出可保存的23位的多余位大于等于 100 … 01 100…01 100…01,则多余位的值超过了最低可表示位值的一半,这种情况下,舍入的方法是在尾数的最低有效位上加1;若多余位小于等于 011 … 11 011…11 011…11,则直接舍去;若多余位为 100 … 00 100…00 100…00,此时再判断尾数的最低有效位的值,若为0则直接舍去,若为1则再加1。
(2)朝 + ∞ +∞ +∞舍入(round toward + ∞ +∞ +∞)对正数来说,只要多余位不为全0,则向尾数最低有效位进1;对负数来说,则是简单地舍去。
(3)朝 − ∞ -∞ −∞舍入(round toward − ∞ -∞ −∞)与朝 + ∞ +∞ +∞舍入方法正好相反,对正数来说,只是简单地舍去;对负数来说,只要多余位不为全0,则向尾数最低有效位进1。
(4)朝0舍入(round toward 0)
即简单地截断舍去,而不管多余位是什么值。这种方法实现简单,但容易形成累积误差,且舍入处理后的值总是向下偏差。
五、 溢出判断
与定点数运算不同的是,浮点数的溢出是以其运算结果的阶码的值是否产生溢出来判断的。若阶码的值超过了阶码所能表示的最大正数,则为上溢,进一步,若此时浮点数为正数,则为正上溢,记为 + ∞ +∞ +∞,若浮点数为负数,则为负上溢,记为 − ∞ -∞ −∞;若阶码的值超过了阶码所能表示的最小负数,则为下溢,进一步,若此时浮点数为正数,则为正下溢,若浮点数为负数,则为负下溢。正下溢和负下溢都作为0处理。
要注意的是,浮点数的表示范围和补码表示的定点数的表示范围是有所不同的,定点数的表示范围是连续的,而浮点数的表示范围可能是不连续的。
六、例子
f l o a t a = 0.3 ; b = 1.6 float \ \ \ \ a=0.3;b=1.6 float a=0.3;b=1.6;
a = ( 0.3 ) 10 = ( 0011 1110 1001 1001 1001 1001 1001 1010 ) 2 a=(0.3)_{10}=(0011\ 1110\ 1001\ 1001\ 1001\ 1001\ 1001\ 1010)_2 a=(0.3)10=(0011 1110 1001 1001 1001 1001 1001 1010)2
S a = 0 E a = 011 1110 1 M a = 1.001 1001 1001 1001 1001 1010 S_a=0\ \ \ \ E_a=011\ 1110\ 1\ \ \ \ M_a=1.001\ 1001\ 1001\ 1001\ 1001\ 1010 Sa=0 Ea=011 1110 1 Ma=1.001 1001 1001 1001 1001 1010b = ( 1.6 ) 10 = ( 0011 1111 1100 1100 1100 1100 1100 1101 ) 2 b=(1.6)_{10}=(0011\ 1111\ 1100\ 1100\ 1100\ 1100\ 1100\ 1101)_2 b=(1.6)10=(0011 1111 1100 1100 1100 1100 1100 1101)2
S b = 0 E b = 011 1111 1 M b = 1.100 1100 1100 1100 1100 1101 S_b=0\ \ \ \ E_b=011\ 1111\ 1\ \ \ M_b=1.100\ 1100\ 1100\ 1100\ 1100\ 1101 Sb=0 Eb=011 1111 1 Mb=1.100 1100 1100 1100 1100 1101a + b = ? a+b=? a+b=?
二进制浮点数加法
第一步:对阶
∵ E a < E b E b − E a = 2 ∵ E_a < E_b\ \ \ E_b-E_a=2 ∵Ea<Eb Eb−Ea=2
∴ M a 要 调 整 为 0.0 1001 1001 1001 1001 1001 10 10 ∴ Ma要调整为 0.0\ 1001\ 1001\ 1001\ 1001\ 1001\ 10\ \ \ \ \ \ \ 10 ∴Ma要调整为0.0 1001 1001 1001 1001 1001 10 10
E = 011 1111 1 E=011\ \ 1111\ \ 1 E=011 1111 1
第二步:尾数运算
0.01001100110011001100110 \ \ \ \ 0.01001100110011001100110 0.01001100110011001100110
+ 1.10011001100110011001101 +\ 1.10011001100110011001101 + 1.10011001100110011001101
= 1.11100110011001100110011 =1.11100110011001100110011 =1.11100110011001100110011第三步:规格化
1.11100110011001100110011 1.11100110011001100110011 1.11100110011001100110011已经是个规格化数据了
第四步:舍入处理
由于在对阶时, M a M_a Ma有右移,且第一次最高为1,第二次为0,所以按"0舍1入",尾数运算结果调整为 1.11100110011001100110100 1.11100110011001100110100 1.11100110011001100110100
第五步:溢出判断
没有溢出,阶码不调整,所以最后的结果为
a + b = ( 0 01111111 11100110011001100110100 ) 2 = ( 0011 1111 1111 0011 0011 0011 0011 0100 ) 2 = ( 3 F F 33334 ) 16 a+b=(0\ \ 01111111\ \ 11100110011001100110100)_2=(0011\ 1111\ 1111\ 0011\ 0011\ 0011\ 0011\ 0100)_2=(3FF33334)_{16} a+b=(0 01111111 11100110011001100110100)2=(0011 1111 1111 0011 0011 0011 0011 0100)2=(3FF33334)16
转为10进制
a + b = 1.90000010 a+b=1.90000010 a+b=1.90000010
二进制浮点数减法
b − a = ? b-a=? b−a=?
第一步:对阶跟上面加法一样
第二步:尾数运算
1.10011001100110011001101 \ \ \ \ 1.10011001100110011001101 1.10011001100110011001101
− 0.01001100110011001100110 -\ 0.01001100110011001100110 − 0.01001100110011001100110
= 1.01001100110011001100111 =1.01001100110011001100111 =1.01001100110011001100111
第三步:规格化
1.01001100110011001100111 1.01001100110011001100111 1.01001100110011001100111已经是个规格化数据了
第四步:舍入处理
由于在对阶时, M a M_a Ma有右移,且第一次最高为1,第二次为0,所以按"0舍1入",尾数运算结果调整为 1.01001100110011001100110 1.01001100110011001100110 1.01001100110011001100110
第五步:溢出判断
没有溢出,阶码不调整,所以最后的结果为
a − b = ( 0 01111111 01001100110011001100110 ) 2 = ( 0011 1111 1010 0110 0110 0110 0110 0110 ) 2 = ( 3 F A 66666 ) 16 a-b=(0\ \ 01111111\ \ 01001100110011001100110)2=(0011\ \ 1111\ \ 1010\ \ 0110\ \ 0110\ \ 0110\ \ 0110\ \ 0110)_2=(3FA66666)_{16} a−b=(0 01111111 01001100110011001100110)2=(0011 1111 1010 0110 0110 0110 0110 0110)2=(3FA66666)16
转为10进制
a − b = 1.29999995 a-b=1.29999995 a−b=1.29999995
二进制浮点数乘法
浮点数的乘法分为以下几个步骤:
计算符号位:通过异或操作计算符号位,若两个操作数符号位相同,则结果符号位为0,否则结果符号为1
计算原始尾数:两个操作数的尾数相乘(注意,这里是1.M * 1.M),得到原始尾数
计算原始指数:将两个操作数的指数(这里指的是指数幂次方,也就是阶码-移码后得到的数)相加,得到原始指数
规格化与舍入:对原始尾数和原始指数进行规格化,获得结果的指数,再对尾数进行舍入,获得结果的尾数f l o a t X = − 0.3 ; Y = 500.25 float \ \ \ \ X=-0.3;Y=500.25 float X=−0.3;Y=500.25;
X = ( − 0.3 ) 10 = ( 0.010011001100110011... 循 环 ) 2 = ( 1.00110011... 循 环 ) 2 ∗ 2 − 2 = ( 1 01111101 00110011001100110011010 ) 2 ( 这 里 对 无 限 循 环 小 数 有 舍 入 处 理 ) X=(-0.3)_{10}=(0.010011001100110011...循环)_{2}=(1.00110011...循环)_2 * 2^{-2}=(1\ \ 01111101\ \ 00110011001100110011010)_2(这里对无限循环小数有舍入处理) X=(−0.3)10=(0.010011001100110011...循环)2=(1.00110011...循环)2∗2−2=(1 01111101 00110011001100110011010)2(这里对无限循环小数有舍入处理)
Y = ( 500.25 ) 10 = ( 111110100.01 ) 2 = ( 1.1111010001 ) 2 ∗ 2 8 = ( 0 10000111 11110100010000000000000 ) 2 Y=(500.25)_{10}=(111110100.01)_2=(1.1111010001)_2*2^{8}=(0\ \ 10000111\ \ 11110100010000000000000)_2 Y=(500.25)10=(111110100.01)2=(1.1111010001)2∗28=(0 10000111 11110100010000000000000)2X ∗ Y = ( X s ∗ Y s ) ∗ 2 X E + Y E X*Y=(X_s*Y_s)*2^{X_E+Y_E} X∗Y=(Xs∗Ys)∗2XE+YE
X E = − 2 X s = 1.00110011001100110011010 X_E=-2\ \ \ \ \ \ \ \ \ \ \ X_s=1.00110011001100110011010 XE=−2 Xs=1.00110011001100110011010
Y E = 8 Y s = 1.1111010001 Y_E=8\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Y_s=1.1111010001 YE=8 Ys=1.1111010001
X s 1.0011001100110011001101 \ \ X_s\ \ \ \ \ \ \ \ 1.0011001100110011001101 Xs 1.0011001100110011001101
∗ Y s ∗ 1.1111010001 *\ Y_s\ \ \ \ *\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 1.1111010001 ∗ Ys ∗ 1.1111010001
= 10.01011000010011001100111001011101 =10.01011000010011001100111001011101 =10.01011000010011001100111001011101X ∗ Y = 10.01011000010011001100111001011101 ∗ 2 6 X*Y=10.01011000010011001100111001011101*2^6 X∗Y=10.01011000010011001100111001011101∗26
= 1.001011000010011001100111001011101 ∗ 2 7 ( 右 规 操 作 ) \ \ \ \ \ \ \ \ \ \ \ \ =1.001011000010011001100111001011101*2^7(右规操作) =1.001011000010011001100111001011101∗27(右规操作)结果二进制就为(注意,上面的指数7要加上移码才是存在指数位中的阶码,即7+127=134)
( 1 10000110 00101100001001100110100 ) 2 (1\ \ 10000110\ \ 00101100001001100110100)_2 (1 10000110 00101100001001100110100)2
至于最后的尾数是怎么得到,是由原始尾数(X和Y的尾数相乘后得到)经过舍入得到二进制浮点数除法
除法与乘法相差不大,变更为指数相减,尾数相除。
f l o a t X = 91.34375 ; Y = 0.14453125 float \ \ \ \ X=91.34375;Y=0.14453125 float X=91.34375;Y=0.14453125;
X = ( 91.34375 ) 10 = ( 1011011.01011 ) 2 = ( 1.01101101011 ) 2 ∗ 2 6 = ( 0 10000101 01101101011000000000000 ) 2 X=(91.34375)_{10}=(1011011.01011)_{2}=(1.01101101011)_2 * 2^{6}=(0\ \ 10000101\ \ 01101101011000000000000)_2 X=(91.34375)10=(1011011.01011)2=(1.01101101011)2∗26=(0 10000101 01101101011000000000000)2
Y = ( 0.14453125 ) 10 = ( 0.00100101 ) 2 = ( 1.00101 ) 2 ∗ 2 8 = ( 0 01111100 00101000000000000000000 ) 2 Y=(0.14453125)_{10}=(0.00100101)_2=(1.00101)_2*2^{8}=(0\ \ 01111100\ \ 00101000000000000000000)_2 Y=(0.14453125)10=(0.00100101)2=(1.00101)2∗28=(0 01111100 00101000000000000000000)2X / Y = ( X s / Y s ) ∗ 2 X E − Y E = ( X s / Y s ) ∗ 2 6 − ( − 3 ) X/Y=(X_s/Y_s)*2^{X_E-Y_E}=(X_s/Y_s)*2^{6-(-3)} X/Y=(Xs/Ys)∗2XE−YE=(Xs/Ys)∗26−(−3)
X E = 6 X s = 1.01101101011 X_E=6\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ X_s=1.01101101011 XE=6 Xs=1.01101101011
Y E = − 3 Y s = 1.00101 Y_E=-3\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ Y_s=1.00101 YE=−3 Ys=1.00101
X s 1.01101101011 \ \ X_s\ \ \ \ \ \ \ \ 1.01101101011 Xs 1.01101101011
/ Y s / 1.00101 /\ Y_s\ \ \ \ /\ \ 1.00101 / Ys / 1.00101
= 1.001111 =1.001111 =1.0011119 + 127 = 136 9+127 = 136 9+127=136
( 0 10001000 00111100000000000000000 ) 2 (0\ \ 10001000\ \ 00111100000000000000000)_2 (0 10001000 00111100000000000000000)2
浮点运算逻辑电路
Reference
https://zhuanlan.zhihu.com/p/58731780
https://www.yuejianzun.xyz/2019/05/28/%E6%B5%AE%E7%82%B9%E6%95%B0%E5%A4%84%E7%90%86/
https://www.cnblogs.com/yilang/
https://www.youtube.com/watch?v=MiOtePebraQ
https://www.youtube.com/watch?v=27JjUa-eu_E&t=11s
https://www.youtube.com/watch?v=fi8A4zz1d-s -
java二进制运算
2020-08-20 18:57:25保留符号位,其余的向左移动N位,整数和负数都是低位补0,相当于乘以2的N次方,这种方式用来做2的整数倍乘法运算效率很高。 .>> 保留符号位,其余的向右移动N位,整数高位补0,负数高位补1 . &前言
在讲二进制运算之前,首先得知道原码,反码,补码的概念。举个例子。
二进制运算
- & 按位逻辑与,都为1则为1,否则为0;
- | 按位或,都为0则为0,有一个为1则为1;
- ^ 异或,两个都相同为0,两个不相同为1,11=0,10=1,0^0=0
- ~ 按位取反,包括符号位;
- << 保留符号位,其余的向左移动N位,整数和负数都是低位补0,相当于乘以2的N次方,这种方式用来做2的整数倍乘法运算效率很高。
- .>> 保留符号位,其余的向右移动N位,整数高位补0,负数高位补1
- . >>> 将符号位也一起移动,高位补0,正数跟>>一样,负数因为符号位是1,移动后的结果可能不是我们预期的。
- 对于 int 类型的整数移位 a >> b, 当 b>32 时,系统先用 b 对 32 求余(因为 int 是 32 位),得到的结果才是真正移位的位数,例如,a >> 33 和 a >> 1 的结果相同,而 a >> 32 = a;对于 long 类型的整数移位 a >> b, 当 b>64 时,系统先用 b 对 64 求余(因为 long 是 64 位),得到的结果才是真正移位的位数;当进行移位运算时,只要被移位的二进制码没有发生有效位的数字丢失(对于正数而言,通常指被移出去的位全部是 0),不难发现左移 n 位就相当于乘以 2 的 n 次方,右移 n 位则是除以 2 的 n 次方;
- ~n=-(n+1),3的按位取反 = -4
- -n&n = 整数n的二进制字符串最后一个1所代表的整数,比如-10 & 10 = 2
- == n&(n-1) = 整数n的二进制串去掉最后一个1之后 的整数 ==,比如 10 & 9 = 8
思考题1
int有32位,有什么方法可以判断这个int中有多少位是1?
可以直接用Integer.bitCount函数,也可以自定义一个。private static int cnt(int value){ int count = 0; while(value != 0){ value &= (value -1); count++; } return count; }
测试代码
public static void main(String[] args) { int a = 10; //00000000000000000000000000001010 int b = -10; //11111111111111111111111111110110 System.out.println("a="+a); System.out.println("a的二进制表示:"); System.out.println(Integer.toBinaryString(a)); System.out.println("a的二进制表示中1的位数="+Integer.bitCount(a)); System.out.println("a的二进制表示中1的位数="+cnt(a)); System.out.println("====================="); System.out.println("b="+b); System.out.println("b的二进制表示:"); System.out.println(Integer.toBinaryString(b)); System.out.println("b的二进制表示中1的位数="+Integer.bitCount(b)); System.out.println("b的二进制表示中1的位数="+cnt(b)); }
结果输出
a=10 a的二进制表示: 1010 a的二进制表示中1的位数=2 a的二进制表示中1的位数=2 ===================== b=-10 b的二进制表示: 11111111111111111111111111110110 b的二进制表示中1的位数=30 b的二进制表示中1的位数=30 Process finished with exit code 0
思考题2
有a,b两个整数,如何用位运算实现a+b??
主要考虑用 位异或(也称不进位加) , 按位与 运算来实现。public static int add(int a ,int b){ // 异或运算有一个别名叫做:不进位加法 // 那么a ^ b就是a和b相加之后,该进位的地方不进位的结果 // 然后下面考虑哪些地方要进位,自然是a和b里都是1的地方 // a & b就是a和b里都是1的那些位置,a & b << 1 就是进位之后的结果。 // 所以:a + b = (a ^ b) + (a & b << 1) // 比如:1 + 1 = (1 ^ 1) + (1 & 1 << 1) // 可以知道,这个过程是在模拟加法的运算过程,进位不可能 // 一直持续,所以b最终会变为0。因此重复做上述操作就可以 // 求得a + b的值。 while (b != 0) { int bujinwei_jia = a ^ b; int jinwei = (a & b) << 1; a = bujinwei_jia; b = jinwei; } return a; }
-
二进制加,减法,23个位运算技巧
2019-04-06 20:36:22二进制加,减法 二进制最高位为1时表示负数,为0时表示正数。 **原码:**一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码。 举例说明: int类型的 3 的... -
二进制计算
2021-07-21 05:31:49虽然很早就接触了二进制,却一直没有正视这个问题,阅读《计算机科学导论》的时候,基本上是跳过了这一部分,总是以“这么基础的东西,反正工作中基本用不上”的理由给搪塞过去。最近正在阅读《编码》和《程序员的... -
整数的二进制、位运算、逻辑与或
2019-10-03 11:14:06二进制 正整数的二进制表示 (假定类型是byte) 正整数的二进制表示与此类似, 只是在十进制中,每个位置可以有10个数字,从0到9,但在二进制中,每个位置只能是0或1。 例如: 0000 1010 ==> 10 负整数... -
二进制及其运算学习(原码、反码、补码、位运算)
2020-05-03 22:18:52学习背景:最近在看很多JAVA类的源码,遇到了很多的位运算,所以系统的学习了下有关二进制的知识。 首先,看一下JAVA中的基本数据的字节(Byte)长度和bit长度: 基本数据类型 字节Byte bit byte 1字节 8位 ... -
二进制乘法原理
2015-03-21 21:29:41二进制乘法原理:就是左移(进位)8次,每次最高位为1则加进去,8位移完就得出乘积了实际上和我们做10进制的乘法是一样的,只不过这里的进制是2罢了比如5×6,转成二进制就是0101×0110 十进制乘法大家都会做,公式... -
不使用累计乘法的基础上,通过移位运算( )实现2的n次方的计算(c语言)
2022-01-31 15:51:17)实现2的n次方的计算。 数据范围:0≤n≤31 输入描述: 一行输入整数n(0 <= n < 31)。 输出描述: 输出对应的2的n次方的结果。 示例1 输入: 2 输出: 4 移位操作符运算规则: (1)右移操作符:... -
2/27坚持学习(递归、位运算二进制)
2019-02-27 22:42:44剑指offer ...求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。 class Solution: def jumpFloor(self, number): # write code here if number <=2: return number ... -
超有趣的二进制—高效位运算秒懂
2019-05-20 17:38:23位运算速度要快于整数运算的,特别是整数乘法,需要10个或者更多个时钟,若果采用移位操作一个或者2个时钟就够了,不过由于我们常采用十进制来进行算术运算,对二进制的位运算不够熟悉,阅读起来会比较耗费精力,... -
二进制运算与转换
2019-10-27 14:35:32二进制是逢2进位的进位制,0、1是基本算符。现代的电子计算机技术全部采用的是二进制,因为它只使用0、1两个数字符号,非常简单方便,易于用电子方式实现。计算机内部处理的信息,都是采用二进制数来表示的。二进制... -
一篇文章彻底弄明白java中的二进制运算
2018-09-30 20:14:47在java中的二进制运算符有:<<(左移保留符号位), >...在说二进制运算之前,我们先来了解一下原码,反码和补码的概念: 原码:第一位是符号位,0表示正数,1表示负数。其余3... -
计算机基础:15、二进制--进制运算基础
2021-06-12 10:32:36计算机基础:15、二进制--进制运算基础1、进制概述1.1、进制定义和举例2、常见进制3、二进制运算基础3.1、按权展开法3.2、重复相除法3.3、重复相乘法 1、进制概述 1.1、进制定义和举例 进制的定义 进制是一种计数... -
二进制转十进制
2021-06-19 04:51:4764个基数为:"[emailprotected]"注意:本工具只是各种进制计数法的数之间的转换,计算机表示数的方法是进行编码表示,整数有整数的表示方法,浮点数有浮点数的表示方法,所以本工具不能直接把计算机中二进制表示的数... -
二进制是如何将加减乘除变换为加法实现的
2021-07-28 07:05:09二进制是如何将加减乘除变换为加法实现的?加法是如何由逻辑运算与、或、异或来实现的?...乘法由于计算机中,所有数值都是用2的N次方来表示的:2^n0+2^n1+2^n2+2^n3+2^n4.....因此x*y,(x)*(2^n0+2^n1+2^n2+2^n3+2^n4... -
位运算解决常见问题--求二进制中1的个数,判断是否是2的次幂等
2019-07-17 18:05:011、什么是位运算?...而位运算就是直接在二进制的数字序列上进行按位与,按位或,按位异或,左移,右移这几种操作。 由于计算机内部本身就是以二进制在运算,所以位运算相较算数运算符来说,计算起来就... -
二进制编码once ok:原码 补码 反码 乘法运算 定点数 浮点数
2022-03-07 21:16:14表示范围2的n次方-1。 有符号数: 原码:用尾数表示真值的绝对值,符号位“0/1”对应“正/负” 若机器字长为n+1位,则尾数占n位。 原码:原码通常用来表示定点小数,用来表示浮点数的尾数。 原码就是用最高位来... -
使用二进制和位移运算实现简单的算法
2018-10-02 09:58:351.将一个二进制数向左位移n位就等于该数乘以2的n次方,当乘法运算中的某个数符合这个特点的时候,可以用位移运算代替乘法运算,从而提高效率。 package pp.suanfa; /** * 乘法运算转位移运算 * * @author ... -
位运算的妙用_判断2的乘方和二进制1的个数
2016-11-23 21:07:31本来定好每个星期写一遍算法的博客的,可是因为最近赶项目,博客停止更新一段时间了,现在抽空继续...题目:实现一个方法,判断一个正整数是否是2的乘方(比如 16 是 2 的 4 次方,返回 True;18 不是 2 的乘方,返回 F -
二进制数的补码及运算(2)
2017-02-26 12:04:48本章均对整数进行操作,小数情况请先转化为整数并对其符号位。 -
大数运算 (10进制与2进制)
2020-02-18 13:10:03最近完成了数据结构的课程设计,课程设计的题目选择的是...非对称密码在加密和解密时,是把 加密的数据当作一个大的正整数来处理,这样就涉及到大整数的加、减、乘、除和指数运算 等,同时,还需要对大整数进行输出... -
用最有效率的方法算出 2 乘以 8 等於几? 和 二进制转十进制,十进制转二进制
2021-03-09 19:44:373 ,即是2乘以2的3次方。由于这里涉及到左移位运算,简单科普下左移位运算,(左移位运算的公式:a<1)例: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。2)... -
二进制整数的乘除运算
2017-06-13 15:46:00运算一直视程序执行其中一个重要的环节,而在二进制的运算过程其中,加法运算有时重中之重,他基本上奠定了二进制运算的基础.因此不管是减法还是乘法,都能够由加法运算来取代,只有除法不能取代. 了解了计算机运算的... -
c++中计算2得n次方_如何用简短代码快速计算fibonacci数列
2020-10-27 10:23:30起初是CCSP 2019的一道代码优化卡常数的题,有一个数据点就是算斐波那契数列第n项模某个质数p的的结果。但是因为矩阵快速幂常数太大,卡的非常难受,于是回去想了想有没有简洁优美一点的代码。问题:对输入 ,计算... -
Python二进制转十进制算法、十进转二进制算法
2020-11-21 03:03:12二进制数转换成十进制数:二进制数从右向左每位数乘以2的次方(从0开始,从右向左依次+1),然后相加求和即可如:0101转成十进制为:1*20+0*21+1*22+0*23=1+0+4+0=5算法实现:#coding=utf-8b=raw_input("请输入一个... -
LeetCode刷题——剑指offer位运算题目汇总(包含快速乘、快速幂、二进制加法)
2022-02-03 10:53:58剑指offer位运算题目汇总: 剑指 Offer II 001; 剑指 Offer II 002; 剑指 Offer II 003; 剑指 Offer II 004; 剑指 Offer II 005; 剑指 Offer 15; 剑指 Offer 16; 剑指 Offer 64; 剑指 Offer 65; -
透彻理解快速幂运算&取模乘法性质(附核心代码模板)
2022-03-01 11:23:37快速幂运算&取模乘法性质的知识点与相关题型精析,与相应实用代码模板。 -
十进制转二进制例题
2021-06-09 05:38:08)十进制转二进制简单的来讲,就是把一个十进制的数÷2,一直÷,直到不能除了,就像是1÷2,在十进制转二进制的时候,它的答案为0,没有余数就写0,然后把前面的余数全部合并在一起,不是加在一起,如果第一个数是0...