2.55 编译运行下列代码,并且确定机器字节顺序。
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len) { // size_t == unsigned 8bit integer
size_t i;
for (i = 0; i < len; ++i) {
printf("%.2x ", start[i]);
}
printf("\n");
}
void show_int(int x) {
show_bytes((byte_pointer) &x, sizeof(int));
}
void show_float(float x) {
show_bytes((byte_pointer) &x, sizeof(float));
}
void show_pointer(void *x) {
printf("x's address value is [%p] \n", x);
show_bytes((byte_pointer) &x, sizeof(void *));
}
void test_show_bytes(int val) {
int ival = val;
float fval = (float) ival;
int *pval = &ival;
show_int(ival);
show_float(fval);
show_pointer(pval);
}
int main(void) {
int test_number = 1234;
test_show_bytes(test_number); // 1234 == 100 1101 0010 == 00 00 04 d2(大端) == d2 04 00 00 (小端)
return 0;
}
我的机器是小端顺序,intel 基本上都是小端。
为什么 byte_pointer 使用 unsigned char * (而不是 char *)?
#include <stdio.h>
int main()
{
char c = 129;// 1000 0001 11111111 1000 0001
char unsigned uc = 129;
printf("%d\n", c);
printf("%x\n", c);
printf("%d\n", uc);
printf("%x\n", uc);
return 1;
}
/* 输出
-127
ffffff81
129
81
* /
2.56 试着用不同示例值运行上面的代码。
同上。
2.57 同上面一样去编写程序 show_short, show_long, show_double 并运行。
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i = 0; i < len; ++i) {
printf("%.2x ", start[i]);
}
printf("\n\n");
}
void show_short(short x) {
show_bytes((byte_pointer) &x, sizeof(short));
}
void show_long(long x) {
show_bytes((byte_pointer) &x, sizeof(long));
}
void show_double(double x) {
show_bytes((byte_pointer) &x, sizeof(double));
}
void test_show_bytes(int ival) {
short sval = (short) ival;
long lval = (long) ival;
double dval = (double) ival;
show_short(sval);
show_long(lval);
show_double(dval);
}
int main(void) {
test_show_bytes(0x12345678);
return 0;
}
78 56
78 56 34 12
00 00 00 78 56 34 b2 41
2.58 编写 is_little_endian 函数判断大端还是小端,返回 0 和 1。
#include <stdio.h>
int main() {
int i = 65538; // 00000000 00000001 00000000 00000010
unsigned char *j = (unsigned char *) &i;
if (*j == 2) {
printf("1");
return 1; // little endian
}
printf("0");
return 0;
}
2.59 编写程序返回 x 的最低有效字节,和 y 中剩下的字节。
#include <stdio.h>
int main() {
int i = 65538; // 0x10002
int j = 12345; // 0x3039
printf("%x", (i & 0xff) | (j & ~0xff));
return 1;
}
2.60 将字节从 0 开始编号,写出函数实现将参数 x 的字节 i 被替换成字节 b。
#include <stdio.h>
#include <assert.h>
int replace_byte(unsigned x, unsigned char i, unsigned char b) {
return ((-1 - (0xff << (i << 3))) & x) | (b<<(i<<3));
}
int main() {
unsigned rep_0 = replace_byte(0x12345678, 0, 0xAB);
unsigned rep_3 = replace_byte(0x12345678, 3, 0xAB);
assert(rep_0 == 0x123456AB);
assert(rep_3 == 0xAB345678);
return 1;
}
2.61
#include <stdio.h>
int get_msb(int x) {
return ((!x)
| (!(~x))
| (!((~(x & 0xff)) & 0xff))
| (!(x >> ((sizeof(x) - 1)<<3 ))));
}
int main() {
printf("%d", get_msb(0xff));
printf("%d", get_msb(0));
printf("%d", get_msb(0x11ff));
printf("%d", get_msb(0xff00));
printf("%d", get_msb(0xffff00));
return 1;
}
2.62
#include <stdio.h>
int main() {
int a = -1;
int res = !(~(a >> 1));
printf("%d", res);
return 1;
}
2.63
#include <stdio.h>
unsigned srl(unsigned x, int k) {
unsigned xsra = (int) x >> k;
return (~(-1 << ((sizeof(int) << 3) - k))) & xsra;
}
int main() {
unsigned a = 0xffffffff;
unsigned v = srl(a, 3);
printf("%x", v);
return 1;
}
#include <stdio.h>
unsigned sra(int x, int k) {
unsigned xsrl = (unsigned) x >> k;
int bits = sizeof(int) << 3;
return (-!!(1 << (bits - 1) & x)) << (bits - k) | xsrl;
}
int main() {
unsigned a = 0xffffffff;
unsigned v = sra(a, 15);
printf("%x", v);
return 1;
}
2.64
#include <stdio.h>
int any_odd_one(unsigned x) {
return !!(x & 0xaaaaaaaa);
}
int main() {
unsigned a = 0x5;
int b = any_odd_one(a);
printf("%d", b);
return 1;
}
2.55
#include <stdio.h>
#include <assert.h>
int odd_ones(unsigned x) {
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
x &= 0x1;
return x;
}
int main(int argc, char *argv[]) {
assert(odd_ones(0x10101011));
assert(!odd_ones(0x01010101));
return 0;
}
2.66
#include <stdio.h>
#include <assert.h>
unsigned left_most_one(unsigned x) {
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return (x + 1) >> 1;
}
int main() {
assert(left_most_one(0xff00) == 0x8000);
assert(left_most_one(0x6600) == 0x4000);
return 1;
}
2.67
- c11 标准指出:如果右移的位数为负数,或者左移的位数大于等于数值宽度,则结果在标准中未定义。
- 和 3.
#include <stdio.h>
#include <assert.h>
int int_size_is_32() {
int set_msb = 1 << 31;
int beyond_msb = set_msb << 1;
return set_msb && !beyond_msb;
}
int int_size_is_32_for_16bit() {
int set_msb = 1 << 15 << 15 << 1;
int beyond_msb = set_msb << 1;
return set_msb && !beyond_msb;
}
int main(int argc, char *argv[]) {
assert(int_size_is_32());
assert(int_size_is_32_for_16bit());
return 0;
}
2.68
#include <stdio.h>
#include <assert.h>
int lower_one_mask(int n) {
return ~(-1 << n);
}
int main() {
assert(lower_one_mask(6) == 0x3f);
assert(lower_one_mask(17) == 0x1ffff);
return 1;
}
2.69
#include <stdio.h>
#include <assert.h>
unsigned rotate_left(unsigned x, int n) {
return (x << n) | (x >> ((sizeof(x) << 3) - n));
// 这么写不对,考虑 n = w 的情况,左移位数等于数值宽度,在 c 标准中未规范
// return (x << (n-1)<<1) | (x >> ((sizeof(x) << 3) - n));
}
int main() {
assert(rotate_left(0x12345678, 4) == 0x23456781);
assert(rotate_left(0x12345678, 20) == 0x67812345);
assert(rotate_left(0x12345678, 0) == 0x12345678);
return 1;
}
2.70
#include <stdio.h>
#include <assert.h>
int fits_bits(int x, int n) {
int spare = (sizeof(int) << 3) - n;
return x == (x << spare >> spare);
}
int main(int argc, char *argv[]) {
assert(!fits_bits(0xFF, 8));
assert(!fits_bits(~0xFF, 8));
assert(fits_bits(0b0010, 3));
assert(!fits_bits(0b1010, 3));
assert(!fits_bits(0b0110, 3));
assert(fits_bits(~0b11, 3));
assert(!fits_bits(~0b01000011, 3));
assert(!fits_bits(~0b111, 3));
return 0;
}
2.71
书本答案未曾考虑到算术右移。
#include <stdio.h>
#include <assert.h>
typedef unsigned packed_t;
int xbyte(packed_t word, int byteNum) {
packed_t a = (word >> (bytenum << 3)) & 0xff;
return -(a >> 7) << 8 | a;
}
int main(int argc, char *argv[]) {
assert(0x0000000f == xbyte(0x00000f00, 1));
assert(0xffffffff == xbyte(0x0000ff00, 1));
assert(xbyte(0xAABBCCDD, 1) == 0xFFFFFFCC);
assert(xbyte(0x00112233, 2) == 0x11);
return 0;
}
2.72
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
void copy_int(int val, void *buf, int maxbytes) {
if (maxbytes >= (int) sizeof(val)) {
memcpy(buf, (void *) &val, sizeof(val));
}
}
int main() {
int a = 0x12345678;
unsigned maxbytes = sizeof(int);
void *buf = malloc(maxbytes);
copy_int(a, buf, maxbytes);
assert(0x12345678 == *(int *) buf);
int b = 0xffffffff;
copy_int(b, buf, 0);
assert(0x12345678 == *(int *) buf);
assert(0xffffffff != *(int *) buf);
return 1;
}
2.73
#include <stdio.h>
#include <assert.h>
#include <limits.h>
int saturating_add(int x, int y) {
int sum = x + y;
int min = INT_MIN;
int neg_over = (min & x) && (min & y) && !(min & sum);
int poa_over = !(min & x) && !(min & y) && (min & sum);
(negOver && (sum = INT_MIN)) || (posOver && (sum = INT_MAX));
return sum;
}
int main(int argc, char *argv[]) {
assert(INT_MAX == saturating_add(INT_MAX, 0x1234));
assert(INT_MIN == saturating_add(INT_MIN, -0x1234));
assert(0x11 + 0x22 == saturating_add(0x11, 0x22));
return 0;
}
2.74
#include <stdio.h>
#include <assert.h>
#include <limits.h>
int tsub_ok(int x, int y) {
int a = (!!(INT_MIN & x)) && (y == -y);
int b = !((!!(INT_MIN & x)) ^ (!!(INT_MIN & y)));
return a || b;
}
int main(int argc, char *argv[]) {
assert(!tsub_ok(1, INT_MIN));
assert(tsub_ok(1, 3));
assert(tsub_ok(-1, INT_MIN));
assert(!tsub_ok(0x00, INT_MIN));
assert(tsub_ok(0x00, 0x00));
return 0;
}
2.75
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
int signed_high_prod(int x, int y) {
int64_t mul = (int64_t) x * y;
return mul >> 32;
}
unsigned unsigned_high_prod(unsigned x, unsigned y) {
int sig_x = x >> 31;
int sig_y = y >> 31;
int signed_prod = signed_high_prod(x, y);
return signed_prod + x * sig_y + y * sig_x;
}
unsigned another_unsigned_high_prod(unsigned x, unsigned y) {
uint64_t mul = (uint64_t) x * y;
return mul >> 32;
}
int main(int argc, char *argv[]) {
unsigned x = 0x12345678;
unsigned y = 0xffffffff;
assert(another_unsigned_high_prod(x, y) == unsigned_high_prod(x, y));
assert(signed_high_prod(x, y) != unsigned_high_prod(x, y));
return 0;
}
2.76
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
void *another_calloc(size_t nmemb, size_t size) {
if (nmemb == 0 || size == 0) {
return NULL;
}
size_t buf_size = nmemb * size;
if (nmemb == buf_size / size) {
void *ptr = malloc(buf_size);
memset(ptr, 0, buf_size);
return ptr;
}
return NULL;
}
int main(int argc, char *argv[]) {
void *p;
p = another_calloc(0x1234, 2);
assert(p != NULL);
free(p);
p = another_calloc(SIZE_MAX, 2);
assert(p == NULL);
free(p);
return 0;
}
2.77
#include <stdio.h>
#include <assert.h>
int A(int x) {
return (x << 4) + x;
}
int B(int x) {
return x - (x << 3);
}
int C(int x) {
return (x << 6) - (x << 2);
}
int D(int x) {
return (x << 4) - (x << 7);
}
int main(int argc, char *argv[]) {
int x = 0x87654321;
assert(A(x) == 17 * x);
assert(B(x) == -7 * x);
assert(C(x) == 60 * x);
assert(D(x) == -112 * x);
return 0;
}
2.78
#include <stdio.h>
#include <assert.h>
#include <limits.h>
int divide_power2(int x, int k) {
int is_neg = x & INT_MIN;
(is_neg && (x = x + (1 << k) - 1));
return x >> k;
}
int main(int argc, char* argv[]) {
int x = 0x80000007;
assert(divide_power2(x, 1) == x / 2);
assert(divide_power2(x, 2) == x / 4);
return 0;
}
2.79
#include <stdio.h>
#include <limits.h>
#include <assert.h>
int div(int x, int k) {
int is_neg = x & INT_MIN;
is_neg && (x = x + (1 << k) - 1);
return x >> k;
}
int mul3div4(int x) {
return div((x << 2) - x, 2);
}
int main(int argc, char *argv[]) {
int x = 0x87654321;
assert(mul3div4(x) == x * 3 / 4);
return 0;
}
2.80
#include <stdio.h>
#include <limits.h>
#include <assert.h>
int threeforths(int x) {
int is_neg = x & INT_MIN;
int f = x & ~0x3;
int l = x & 0x3;
int fd4 = f >> 2;
int fd4m3 = (fd4 << 1) + fd4;
int lm3 = (l << 1) + l;
int bias = (1 << 2) - 1;
(is_neg && (lm3 += bias));
int lm3d4 = lm3 >> 2;
return fd4m3 + lm3d4;
}
int main(int argc, char *argv[]) {
assert(threeforths(0) == 0);
assert(threeforths(1) == 0);
assert(threeforths(2) == 1);
assert(threeforths(3) == 2);
assert(threeforths(8) == 6);
assert(threeforths(9) == 6);
assert(threeforths(10) == 7);
assert(threeforths(11) == 8);
assert(threeforths(12) == 9);
assert(threeforths(-8) == -6);
assert(threeforths(-9) == -6);
assert(threeforths(-10) == -7);
assert(threeforths(-11) == -8);
assert(threeforths(-12) == -9);
return 0;
}
2.81
-1 << k
~(-1 << k) << j
2.82
错。 x 是 INT_MIN
对。
对。
对。
对。
2.83
#include <stdio.h>
#include <limits.h>
#include <assert.h>
int threeforths(int x) {
int is_neg = x & INT_MIN;
int f = x & ~0x3;
int l = x & 0x3;
int fd4 = f >> 2;
int fd4m3 = (fd4 << 1) + fd4;
int lm3 = (l << 1) + l;
int bias = (1 << 2) - 1;
(is_neg && (lm3 += bias));
int lm3d4 = lm3 >> 2;
return fd4m3 + lm3d4;
}
int main(int argc, char *argv[]) {
assert(threeforths(0) == 0);
assert(threeforths(1) == 0);
assert(threeforths(2) == 1);
assert(threeforths(3) == 2);
assert(threeforths(8) == 6);
assert(threeforths(9) == 6);
assert(threeforths(10) == 7);
assert(threeforths(11) == 8);
assert(threeforths(12) == 9);
assert(threeforths(-8) == -6);
assert(threeforths(-9) == -6);
assert(threeforths(-10) == -7);
assert(threeforths(-11) == -8);
assert(threeforths(-12) == -9);
return 0;
}
2.83
A.
n = 0.yyyyy...
n << k = y.yyyyy... = Y + n
n << k - n = Y
n = Y/(2^k - 1)
B.
(a).
y = 101, Y = 5, k = 3
n = 5/7
(b).
y = 0110, Y = 6, k = 4
n = 2/5
(c).
y = 010011, Y = 19, k = 6
n = 19/63
2.84
#include <stdio.h>
#include <assert.h>
unsigned f2u(float x) {
return *(unsigned *) &x;
}
int float_le(float x, float y) {
unsigned ux = f2u(x);
unsigned uy = f2u(y);
unsigned sx = ux >> 31;
unsigned sy = uy >> 31;
return (ux << 1 == 0 && uy << 1 == 0) || /* both zeros */
(sx && !sy) || /* x < 0, y >= 0 or x <= 0, y > 0 */
(!sx && ux <= uy) || /* x > 0, y >= 0 or x >= 0, y > 0 */
(sx && ux >= uy); /* x < 0, y <= 0 or x <= 0, y < 0 */
}
int main(int argc, char *argv[]) {
assert(float_le(-0, +0));
assert(float_le(+0, -0));
assert(float_le(0, 3));
assert(float_le(-4, -0));
assert(float_le(-4, 4));
return 0;
}
2.85
// 注意题目中并没有说有符号位
bias = 2^(k - 1) - 1
V = 2^E * M
a.
7.0 = 0b111.000...
M = 0b1.11
f = 0b0.11
E = 2
e = bias + E
V = 7.0
结果是 10...1 110...
b.
bias+n 1...
c.
1...101 0...
2.86
0 0...(15) 0 0...(62)1 2^(1-bias-63)
0 0...(14)1 1 0....(63) 2^(1-bias)
0 1...(14)0 1 1...(63) 2^bias * (2-2^-63)
2.87
描述 | Hex | M | E | V | D |
---|---|---|---|---|---|
-0 | 0x8000 | 0 | -14 | -0 | -0.0 |
>2 least | 0x4001 | 1025/1024 | 1 | 1025/512 | 2.00195312 |
512 | 0x6000 | 1 | 9 | 512 | 512.0 |
bigest denormalized | 0x03FF | 1023/1024 | -14 | 1023/(2^24) | 6.09755516e-5 |
-∞ | 0xFC00 | - | - | -∞ | -∞ |
ox3BB0 | 0x3BB0 | 123/64 | -1 | 123/128 | 0.9609375 |
2.88
A bit | A value | B bit | B value |
---|---|---|---|
1 01110 001 | -9/16 | 1 0110 0010 | -9/16 |
0 10110 101 | 13*2^4 | 0 1110 1010 | 13*2^4 |
1 00111 110 | -7/2^10 | 1 0000 0111 | -7/2^10 |
0 00000 101 | 5/2^17 | 0 0000 0001 | 1/2^10 |
1 11011 000 | -2^12 | 1 1110 1111 | -31*2^3 |
0 11000 100 | 3*2^8 | 0 1111 0000 | +oo |
2.89
#include <stdio.h>
#include <assert.h>
#include <limits.h>
/*
* most important thing is that all double number come from ints
*/
/* right */
int A(int x, double dx) {
return (float) x == (float) dx;
}
/* wrong when y is INT_MIN */
int B(int x, double dx, int y, double dy) {
return dx - dy == (double) (x - y);
}
/* right */
int C(double dx, double dy, double dz) {
return (dx + dy) + dz == dx + (dy + dz);
}
/*
* wrong
*
* FIXME I don't know what conditions cause false
*/
int D(double dx, double dy, double dz) {
return (dx * dy) * dz == dx * (dy * dz);
}
/* wrong when dx != 0 and dz == 0 */
int E(double dx, double dz) {
return dx / dx == dz / dz;
}
int main(int argc, char *argv[]) {
int x = 111;
int y = 222;
int z = 333;
double dx = (double) x;
double dy = (double) y;
double dz = (double) z;
printf("%x %x %x\n", x, y, z);
assert(A(x, dx)); // double 可以表示所有32位整数
assert(!B(0, (double) (int) 0, INT_MIN, (double) (int) INT_MIN)); // 溢出问题
assert(C(dx, dy, dz)); // double 可以表示所有32位整数
assert(!D((double) (int) 0x64e73387, (double) (int) 0xd31cb264, (double) (int) 0xd22f1fcd)); // double 并不能表示所有的 64位数,导致舍入问题
assert(!E(dx, (double) (int) 0)); // 除数为零
return 0;
}
2.90
#include <stdio.h>
#include <assert.h>
#include <math.h>
float u2f(unsigned x) {
return *(float*) &x;
}
/* 2^x */
float fpwr2(int x) {
/* Result exponent and fraction */
unsigned exp, frac;
unsigned u;
if (x < 2-pow(2,7)-23) {
/* too small. return 0.0 */
exp = 0;
frac = 0;
} else if (x < 2-pow(2,7)) {
/* Denormalized result */
exp = 0;
frac = 1 << (unsigned)(x - (2-pow(2,7)-23));
} else if (x < pow(2,7)-1+1) {
/* Normalized result */
exp = pow(2,7)-1+x;
frac = 0;
} else {
/* Too big, return +oo */
exp = 0xFF;
frac = 0;
}
/* pack exp and frac into 32 bits */
u = exp << 23 | frac;
/* Result as float */
return u2f(u);
}
int main(int argc, char* argv[]) {
assert(fpwr2(0) == powf(2,0));
assert(fpwr2(100) == powf(2,100));
assert(fpwr2(-100) == powf(2,-100));
assert(fpwr2(10000) == powf(2,10000));
assert(fpwr2(-10000) == powf(2,-10000));
return 0;
}
2.91
A.
0b11.0010010000111111011011
B.
0b11.001001(001)...
C.
第九个
2.92
float_bits float_negate(float_bits f) {
unsigned sign = f >> 31;
unsigned exp = f >> 23 & 0xff;
unsigned frac = f & 0x7fffff;
if (exp == 0xff && frac) {
return f;
}
return (~sign << 31) | (exp << 23) | frac;
}
2.93
float_bits float_absval(float_bits f) {
unsigned sig = f >> 31;
unsigned exp = f >> 23 & 0xFF;
unsigned frac = f & 0x7FFFFF;
int is_NAN = (exp == 0xFF) && (frac != 0);
if (is_NAN) {
return f;
}
return 0 << 31 | exp << 23 | frac;
}
2.94
float_bits float_twice(float_bits f) {
unsigned sig = f >> 31;
unsigned exp = f >> 23 & 0xFF;
unsigned frac = f & 0x7FFFFF;
int is_NAN_or_oo = (exp == 0xFF);
if (is_NAN_or_oo) {
return f;
}
if (exp == 0) {
/* Denormalized */
frac <<= 1;
} else if (exp == 0xFF - 1) {
/* twice to oo */
exp = 0xFF;
frac = 0;
} else {
/* Normalized */
exp += 1;
}
return sig << 31 | exp << 23 | frac;
}
2.95
float_bits float_half(float_bits f) {
unsigned sig = f >> 31;
unsigned rest = f & 0x7FFFFFFF;
unsigned exp = f >> 23 & 0xFF;
unsigned frac = f & 0x7FFFFF;
int is_NAN_or_oo = (exp == 0xFF);
if (is_NAN_or_oo) {
return f;
}
/*
* round to even, we care about last 2 bits of frac
*
* 00 => 0 just >>1
* 01 => 0 (round to even) just >>1
* 10 => 1 just >>1
* 11 => 1 + 1 (round to even) just >>1 and plus 1
*/
int addition = (frac & 0x3) == 0x3;
if (exp == 0) {
/* Denormalized */
frac >>= 1;
frac += addition;
} else if (exp == 1) {
/* Normalized to denormalized */
rest >>= 1;
rest += addition;
exp = rest >> 23 & 0xFF;
frac = rest & 0x7FFFFF;
} else {
/* Normalized */
exp -= 1;
}
return sig << 31 | exp << 23 | frac;
}
2.96
int float_f2i(float_bits f) {
unsigned sig = f >> 31;
unsigned exp = f >> 23 & 0xFF;
unsigned frac = f & 0x7FFFFF;
unsigned bias = 0x7F;
int num;
unsigned E;
unsigned M;
/*
* consider positive numbers
*
* 0 00000000 00000000000000000000000
* ===>
* 0 01111111 00000000000000000000000
* 0 <= f < 1
* get integer 0
*
* 0 01111111 00000000000000000000000
* ===>
* 0 (01111111+31) 00000000000000000000000
* 1 <= f < 2^31
* integer round to 0
*
* 0 (01111111+31) 00000000000000000000000
* ===>
* greater
* 2^31 <= f < oo
* return 0x80000000
*/
if (exp >= 0 && exp < 0 + bias) {
/* number less than 1 */
num = 0;
} else if (exp >= 31 + bias) {
/* number overflow */
/* or f < 0 and (int)f == INT_MIN */
num = 0x80000000;
} else {
E = exp - bias;
M = frac | 0x800000;
if (E > 23) {
num = M << (E - 23);
} else {
/* whether sig is 1 or 0, round to zero */
num = M >> (23 - E);
}
}
return sig ? -num : num;
}
2.97
#include <stdio.h>
#include <assert.h>
#include <limits.h>
typedef unsigned float_bits;
float_bits float_i2f(int i) {
unsigned sign = i & 0x80000000;
if (i == 0) {
return sign;
}
if (i == 0x80000000) {
return 0xcf000000;
}
unsigned transI = i;
if (sign) {
transI = ~i + 1;
}
int noSignI = transI & 0x7fffffff;
int isOne = noSignI & 0x80000000;
int count = 1;
while (!isOne) {
noSignI <<= 1;
isOne = noSignI & 0x80000000;
count++;
}
int exp = 127 + (32 - count);
int frac = (transI << count >> 1 + 8) & 0x7fffff;
int ret = sign | exp << 23 | frac;
if (32 - count > 23) {
int mid = (transI << count >> 1 + 8 << 1 + 8) + 0b100000000;
if (transI << count > mid) {
ret++;
} else {
if (transI << count == mid && frac & 0x1) {
ret++;
}
}
}
return ret;
}
int main() {
unsigned a;
int b;
int arr[] = {1, 2, 4, INT_MAX, INT_MIN, 0, -1, -2, 123456789, 2147483582, 2147483584, 2147483585};
int count = sizeof(arr) / sizeof(int);
for (int i = 0; i < count; i++) {
b = arr[i];
a = float_i2f(b);
printf("\n %d ==>\t", b);
printf(" %f ==>\t", (float) b);
printf(" %f \n", *(float *) (&a));
assert((float) b == *(float *) (&a));
}
return 0;
}
网友评论