整形的储存
- 整形家族包括,无符号整数和有符号整数。(包括char,short,int,long。long long以及对应的unsigned(无符号类型))。//char的字符再实际存的时候其ASCII码值就是整形。
- 一般来说,计算机存储的二进制,所以一般整形都是转换位二进制数字,存储到内存里面去。
- 一个十进制数字直接转换为二进制数字就是该数字的原码,反码就是除了符号位(符号位一般都是第一位)按位取反,反码加一就得到补码。一般来说,进行运算和使用的时候,都是改个数字的源码。(关于整型提升和算术转换之前有,有兴趣的可以看看)
- 以char类型为例子 :
char a = 10;
//可以在编辑器里面去取内存出来看下存储的二进制。(一般表示的表示0x0a)char a = -10;
就是10001010; - 大小端存储。这个和本身机器有关系。 小端存储:数据从低地址处开始存储 。大端存储:数据从高地址处开始存储。
int a =10;
char b = *(char*)*a;
可以取打印这份b的值小端应该是10,大端就是0;
这里还有个例子:
#include <stdio.h>
union S
{
int a;
char b;
};
int main()
{
union S s;
s.a = 10;
printf("%d\n",s.b);
return 0;
}
因为联合体一起用存储位置的原因,所以这里就能很明显看出来。在小端存储上,依然结果是10,大端存储上结果是0。这是因为在低地址字节处存的值的差异,而本身寄存器一次性读取字节先后顺序不同导致。
浮点数的存储。
这个基本就是参考IEEE754标准了。
- 二进制的科学计数法。一个二进制数字B,B = (-1)^s * M * 2^E; 这个表达式里面,s是符号位,M是一个【1,2)之间的数字,E是2的幂级数。比如1.5,那么就是 1.5 = (-1)^0 * 1.5 * 2^0; 3.0 = (-1)^0 * 1.5 *2^1;
- 根据维基百科的资料:单精度浮点数,双精度浮点数存。
前面是单精度浮点数,后面图是双精度浮点数。
可以看见,符号位都是一位。不同的是指数(exponent)和尾数位(fraction)。浮点数的存储,指数位(下面叫做E)的bit位转换,不是直接转换。而是减去一半。因为我们知道指数是有正负的,但是这里表示出来的E是无符号数,所以为了表示负数,把所得的每一个值,减去一半(向下取整),E是8比特位的单精度浮点数就是减去127,那么E是16比特位的就减去1023.
接下来是尾数,我们知道,科学计数法一定1.xxxx 所以,在存储时,为了多一位尾数(提高精度),就省去了表示1的拿一位,剩下的都用来表示尾数。
这里举个例子:1.11*2^2这个数字就表示7.那么在单精度里面存储的方式就是
0 10000001 1100000000000000000000
这就是浮点数5在内存里面所存储的形式.
那么双精度浮点数也是类似的
1.111*2^3 这个数字也就是15,在双精度浮点数表示的形式是
0 10000000010 11100000000000000(剩下一些0,不然看起来压力大,补足就好)
以上就是整形和浮点数的储存了,如果你感觉有帮助,可以点个赞。有问题欢迎评论区指出,感谢观看。
二分查找
示例代码
int binarySearch(int arr[], int l, int r, int x)
{
if(r >= l) {
int mid = l + (r - l) / 2; // 计算中间索引
// 如果元素正好在中间位置
if (arr[mid] == x)
return mid;
// 如果元素大于中间元素,则在右半部分继续查找
if (arr[mid] < x)
return binarySearch(arr, mid + 1, r, x);
// 否则,在左半部分继续查找
return binarySearch(arr, l, mid - 1, x);
}
// 没有找到元素
return -1;
}
虽然很简单,但是有几个值得一提。
我们不妨认为二分是区间缩小,每次查找少一半的区间,来看以下特性
- 凡是存在整形截断的编程语言,二分查找,最后必然左端点,右端点汇聚在同一个点。也就是只剩下一个值。 原因也很简单,任意一个大于1的数,不断/2,在有整形截断的情况下,最后必然有结果是1。
有了二分查找,不如进一步思考,如果求这个数所在该数组的最小区间呢?
- 判出条件自然就是需要改变,R>L
- 然后就是L取mid+1,或者是R取mid-1的问题了,如何抉择呢?
- 实际上,L取mid+1,就是不断让L向前移动,R取mid,那么就保证R所在的值是大于于目标值。且由于整型截断,R与L之间即使只相差1,也会在mid计算时总是计算的是整个区间中间值左边的那一个,这样使得必然是L=mid+1,而使得L与R重合(L=R),让对应的值是 区间是[ arr[R-1],arr[R] ]
- 对应的,你如果取R是mid-1,L=mid,就可能导致死循环,因为整型截断,导致mid=L,而L与R的值相差1时,mid永远时L。
int binarySearch(int arr[], int l, int r, int x)
{
if(r > l) {
int mid = l + (r - l) / 2; // 计算中间索引
// 如果元素正好在中间位置
if (arr[mid] == x)
return mid;
// 如果元素大于中间元素,则在右半部分继续查找
if (arr[mid] < x)
return binarySearch(arr, mid , r, x);
// 否则,在左半部分继续查找
return binarySearch(arr, l, mid - 1, x);
}
// 没有找到元素
return -1;
}