机器码 真数 原码 反码 补码 float的内存表示
来源:互联网 发布:手机淘宝链接 编辑:程序博客网 时间:2024/04/28 18:16
#include<stdio.h>int main(int argc, char** argv){ printf("sizeof(int): %d\n", sizeof(int)); /********* hex格式表示的整数是补码 http://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html 为简洁,计算机没有减法、只有加法; 反码解决减法问题;补码在反码基础上解决0的符号问题(然后用-0表示-128) 正数的反码是其本身 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反. 正数的补码就是其本身 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) [+1] = [00000001]原 = [00000001]反 = [00000001]补 [-1] = [10000001]原 = [11111110]反 = [11111111]补 因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值 ********/ printf("0xFFFFFFFF:\t%d 0x%X\n", 0xFFFFFFFF, 0xFFFFFFFF); printf("0x7FFFFFFF:\t%d 0x%X\n", 0x7FFFFFFF, 0x7FFFFFFF); printf("-0x7FFFFFFF:\t%d 0x%X\n", -0x7FFFFFFF, -0x7FFFFFFF); return 0;}
[root@test-22 leetcode]# !g++g++ -o inttest inttest.cpp ; ./inttest sizeof(int): 40xFFFFFFFF: -1 0xFFFFFFFF0x7FFFFFFF: 2147483647 0x7FFFFFFF-0x7FFFFFFF: -2147483647 0x80000001
https://github.com/xiarendeniao/utils/blob/master/c/verfloat.cpp
#include <stdio.h>#include <stdint.h>#include <string.h>#include <assert.h>typedef int64_t int64;typedef int32_t int32;typedef int16_t int16;typedef int8_t int8;typedef uint64_t uint64;typedef uint32_t uint32;typedef uint16_t uint16;typedef uint8_t uint8;typedef uint32_t DWORD;/*1.int32表示范围和机器码(补码) bin()函数用于验证补码表示形式 int32 [-2^31,2^31-1] [-2147483648,2147483647] -2147483648正数部分超出31bit的表示范围,机器表示形式是-0(10000000 00000000 00000000 00000000) 所以不能用“符号位不变、其余按照正数的二进制形式按位取反再加1”获取-2147483648的补码 2.大头小头(大端序/小端序) big endian / little endian (以下以int32举例) 机器数(补码)只是为了方便运算所约定的计算机底层的数字表示形式,不等同于内存布局,内存布局和大头小头相关 dec(10) = bin(0b00000000 00000000 00000000 00001010) = hex(0xA) hex是补码的十六进制 dec(-10) = bin(0b11111111 11111111 11111111 11111011) = hex(0xA) dec(-1) = bin(0x11111111 11111111 11111111 11111111) = hex(0xFFFFFFFF) 在big endian机器的内存布局(数字的高位部分放在低地址处、低位部分放在高地址处) membin()函数用于验证数字在内存中的形式 dec(10) 00000000 00000000 00000000 00001010 即 00 00 00 0A dec(-10) 11111111 11111111 11111111 11111011 即 FF FF FF FB dec(-1) 11111111 11111111 11111111 11111111 即 FF FF FF FF 在little endian机器的内存布局(数字的高位部分放在高地址处、低位部分放在低地址处) dec(10) 00001010 00000000 00000000 00000000 即 0A 00 00 00 dec(-10) 11111011 11111111 11111111 11111011 即 FB FF FF FF dec(-1) 11111111 11111111 11111111 11111111 即 FF FF FF FF*/char* positive2bin(const int in, char* binstr, bool filling = true){ assert(in >= 0); char* out = binstr; char t[33]; char* tp = t; int r = in; while(r >= 1) { *tp++ = r%2 + 48; r /= 2; } *tp-- = '\0'; assert(tp-t == strlen(t)-1); //fprintf(stderr, "Positive2bin:%12d 0b%s %dbits\n", in, t, strlen(t)); if (filling) for (int i = 0; i < 32-(tp-t+1); i++) *out++ = '0'; while (tp >= t) *out++ = *tp--; //BUG: while(*out++ = *tp--); *out = '\0'; assert(out-binstr == strlen(binstr)); //fprintf(stderr, "--------2bin:%12d 0b%s %dbits\n", in, binstr, strlen(binstr)); return binstr;} char* bin(const int in, char* binstr){ if (in >= 0) return positive2bin(in, binstr); positive2bin(-in, binstr); //按位取反 *binstr = '1'; char* p = binstr + 1; while ( *p != '\0') { if (*p == '0') *p = '1'; else *p = '0'; p++; } p--; //fprintf(stderr, "-----reverse:%12d 0b%s %dbits\n", in, binstr, strlen(binstr)); //+1 while (p > binstr) { if (*p == '0') { *p = '1'; break; } else { *p = '0'; p--; } } if (p == binstr) fprintf(stderr, "overflow: %d\n", in); return binstr;}char* membin(const uint32* in, char* binstr){ char* bp = binstr; char byte[9] = {0}; uint8* p = (uint8*)in; for (int i = 0; i < 4; i++, p++) { //printf("fetched byte %d\n", (uint32)*p); positive2bin(*p, byte, false); char* tp = byte; for (int i = 0; i < 8-strlen(byte); i++) *bp++ = '0'; while (*tp != '\0') *bp++ = *tp++; } *bp = '\0'; //fprintf(stderr, "------v2-bin:%12d 0b%s %dbits\n", in, binstr, strlen(binstr)); return binstr;}//验证补码的表示形式跟内存数据存放(big/little endian)void verf_bin(){ char buff[128] = {0}; char binstr[33] = {0}; uint32 in;begin: printf("please input > "); scanf("%s", buff); if (buff[0] == '0' && (buff[1] == 'x' || buff[1] == 'X')) sscanf(buff, "%x", &in); else sscanf(buff, "%d", &in); if (in != 0x80000000U) //-2147483648,int32的最小值 fprintf(stderr, "positive2bin:%12d 0x%08x 0b%s bin %f\n", in, in, bin((int32)in, binstr), *(float*)&in); fprintf(stderr, "memory--2bin:%12d 0x%08x 0b%s mem %f\n", in, in, membin((uint32*)&in, binstr), *(float*)&in); goto begin; }int main(int argc, char** argv){ char binstr[33] = {0}; uint32 a = 0x7f700001U; printf("0x%8x 0b%s %f\n", a, bin((int)a,binstr), *(float*)&a); //https://android.googlesource.com/platform/dalvik.git/+/f6c387128427e121477c1b32ad35cdcaa5101ba3/libcore/luni/src/main/native/java_lang_Float.c //java源码中把所有nan替换成同一个,这样便于做比较 uint32 nan = 0x7fc00000; printf("+float标准的nan 0x%8x 0b%s %f\n", nan, bin((int)nan,binstr), *(float*)&nan); uint32 b = 0x7f800001U; printf("+float最小的nan 0x%8x 0b%s %f\n", b, bin((int)b,binstr), *(float*)&b); uint32 c = 0x7fffffffU; printf("+float最大的nan 0x%8x 0b%s %f\n", c, bin((int)c,binstr), *(float*)&c); uint32 d = 0xff800001U; printf("-float最大的nan 0x%8x 0b%s %f\n", d, bin((int)d,binstr), *(float*)&d); uint32 e = 0xffffffffU; printf("-float最小的nan 0x%8x 0b%s %f\n", e, bin((int)e,binstr), *(float*)&e); verf_bin(); return 0;}/*[root@test-22 c++-study]# g++ verfloat.cpp -o verfloat; ./verfloat 0x7f700001 0b01111111011100000000000000000001 319014739270789413148584118414533984256.000000+float最小的nan 0x7f800001 0b01111111100000000000000000000001 nan+float最大的nan 0x7fffffff 0b01111111111111111111111111111111 nan-float最大的nan 0xff800001 0b11111111100000000000000000000001 nan-float最小的nan 0xffffffff 0b11111111111111111111111111111111 nanplease input > 0x40000001Upositive2bin: 1073741825 0x40000001 0b01000000000000000000000000000001 bin 2.000000memory--2bin: 1073741825 0x40000001 0b00000001000000000000000001000000 mem 2.000000please input > 0x7f000001Upositive2bin: 2130706433 0x7f000001 0b01111111000000000000000000000001 bin 170141203742878835383357727663135391744.000000memory--2bin: 2130706433 0x7f000001 0b00000001000000000000000001111111 mem 170141203742878835383357727663135391744.000000please input > 0x00000001Upositive2bin: 1 0x00000001 0b00000000000000000000000000000001 bin 0.000000memory--2bin: 1 0x00000001 0b00000001000000000000000000000000 mem 0.000000please input > 0x007fffffUpositive2bin: 8388607 0x007fffff 0b00000000011111111111111111111111 bin 0.000000memory--2bin: 8388607 0x007fffff 0b11111111111111110111111100000000 mem 0.000000please input > 0x3f800000Upositive2bin: 1065353216 0x3f800000 0b00111111100000000000000000000000 bin 1.000000memory--2bin: 1065353216 0x3f800000 0b00000000000000001000000000111111 mem 1.000000*//* 1.NaN https://android.googlesource.com/platform/dalvik.git/+/f6c387128427e121477c1b32ad35cdcaa5101ba3/libcore/luni/src/main/native/java_lang_Float.c 上述URL中NAN的判定规则:指数为无效值 1.xxxx * 2^n 符号 指数(n,+/-) 尾数(1.xxxx..) float(32) 1 8 23 ... 0x7f800001U 0 111 1111 1 000 0000 0000 0000 0000 0001 nan 0x7fffffffU 0 111 1111 1 111 1111 1111 1111 1111 1111 nan 0xff800001U 1 111 1111 1 000 0000 0000 0000 0000 0001 nan 0xffffffffU 1 111 1111 1 111 1111 1111 1111 1111 1111 nan 0x7fc00000U 0 111 1111 1 100 0000 0000 0000 0000 0000 nan 0x40000001U 0 100 0000 0 000 0000 0000 0000 0000 0001 0x7f000001U 0 111 1111 0 000 0000 0000 0000 0000 0001 0x00000001U 0 000 0000 0 000 0000 0000 0000 0000 0001 -> 指数000 0000 0表示的是-127 0x007fffffU 0 000 0000 0 111 1111 1111 1111 1111 1111 0x3f800000U 0 011 1111 1 000 0000 0000 0000 0000 0000 -> 指数011 1111 1表示的是0,尾数全零表示的是1(尾数最高位被约定省略了) [-2^7,2^7-1] [-128,127](转正:约定+127后存入指数区间,即,127左移一位) [-1,254] [?,1111 1110] -1怎么存? -> 应该是舍掉了吧,指数为0(即1.xxx * 2^-127)时浮点的值已经趋近于0了 double(64) 1 11 52 [-2^10,2^10-1] [-1024,1023] [-1,2046](转正:约定+1023后存入指数区间,即,1023左移一位) 0x7ff8000000000000ULL 0 111 1111 1111 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000*/
0 0
- 机器码 真数 原码 反码 补码 float的内存表示
- 数的机器码表示(原码,反码,补码,移码)
- 机器码 原码 反码 补码
- 真值 机器码 原码 反码 补码
- 原码反码补码表示
- 原码、反码、补码、float、ASCII码
- 原码、反码、补码、float、ASCII码
- 原码、反码、补码,计算机中负数的表示
- 原码、反码、补码,计算机中负数的表示
- 原码、反码、补码,计算机中负数的表示
- 什么是原码反码补码 计算机中负数的表示
- 原码、反码、补码,计算机中负数的表示
- 原码、反码、补码,计算机中负数的表示
- 数的二进制表示——原码、反码、补码
- 原码、反码、补码,计算机中负数的表示
- 计算机中整数的表示:原码、反码、补码
- 原码,反码,补码的表示范围总结
- (笔记)原码、反码和补码的表示方法
- 生成模型与判别方法
- PHP面向对象基础笔记一
- 数据机构(六) 链栈的基本操作
- (转)完整的 mime type 列表
- JavaScript实现年月日三级联动
- 机器码 真数 原码 反码 补码 float的内存表示
- AngularJS学习之修饰符
- malloc和free的实现原理
- Linux--tree命令实现
- 信号量的实现和应用
- 运维基础知识第一次作业
- java中的多态
- 数据机构(五) 顺序栈的基本操作 --- 包含初始化,入栈和出栈
- POJ 0809 求逆序对数(归并排序求逆序数)