Last active
February 20, 2022 17:44
-
-
Save LucaXiang/5f5d6dd07da01b471aedeaedc6d38016 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _CRT_SECURE_NO_WARNINGS | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <math.h> | |
#define is_digit(n) (n >= '0' && n <= '1') | |
typedef union { | |
float f; | |
struct | |
{ | |
unsigned int fraction : 23; | |
unsigned int exponent : 8; | |
unsigned int sign : 1; | |
} raw; | |
} Float; | |
void remove_prefix_zero(char* str) | |
{ | |
char* p = str; | |
while (*p == '0') { | |
p++; | |
}; | |
int index = 0; | |
do | |
{ | |
str[index++] = *p; | |
} while (*p++ != '\0'); | |
} | |
uint64_t convert_to_number(const char* str) | |
{ | |
uint64_t number = 0; | |
int len = 0; | |
const char* p = str; | |
while (*p != '\0') | |
{ | |
if (len != 0) | |
{ | |
number *= 10; | |
} | |
uint8_t n = *p - '0'; | |
number += n; | |
len++; | |
p++; | |
} | |
return number; | |
} | |
void to_bitcode_string(const uint64_t value, const uint64_t field_count, char* buffer) | |
{ | |
uint64_t right = 1ll << field_count - 1; | |
for (int i = 0; i < field_count; i++) | |
{ | |
buffer[i] = value & right ? '1' : '0'; | |
right >>= 1; | |
} | |
} | |
int string_dec_to_banary( char* str, char *buff) | |
{ | |
uint64_t number = convert_to_number(str); | |
if (number == 0) | |
{ | |
buff[0] = '0'; | |
} | |
else | |
{ | |
to_bitcode_string(number, 32, buff); | |
remove_prefix_zero(buff); | |
} | |
return strlen(buff); | |
} | |
int string_decimal_dec_to_binary(char* str, char* buff) { | |
uint64_t number = convert_to_number(str); | |
if (number == 0) | |
{ | |
buff[0] = '0'; | |
} | |
else | |
{ | |
const int max = 23; | |
char temp[100] = { 0 }; | |
strncat(temp, "0.", 2); | |
strcat(temp, str); | |
double number = atof(temp); | |
int index = 0; | |
while (number > 0 && index < max) | |
{ | |
int temp = (int)(number *= 2); | |
buff[index] = temp ? '1' : '0'; | |
index++; | |
if (number >= 1) | |
{ | |
number -= 1; | |
} | |
} | |
} | |
return strlen(buff); | |
} | |
void dump_float(float number) | |
{ | |
const Float* pointer = (Float*)&number; | |
Float f = *pointer; | |
char buffer_integer[33] = { 0 }; | |
const int integer = *(int*)pointer; | |
printf("Float: %f\n", *(float*)pointer); | |
printf("DEC: %d\n", integer); | |
printf("HEX: %x\n", integer); | |
printf("Binary: "); | |
to_bitcode_string(integer, 32, buffer_integer); | |
printf("%s\n\n", buffer_integer); | |
char buffer_sign[2] = { 0 }; | |
char buffer_exp[9] = { 0 }; | |
char buffer_fraction[24] = { 0 }; | |
to_bitcode_string(f.raw.sign, 1, buffer_sign); | |
to_bitcode_string(f.raw.exponent, 8, buffer_exp); | |
to_bitcode_string(f.raw.fraction, 23, buffer_fraction); | |
printf("%-5s | %-10s | %-20s \n", "Sign", "Exponent", "Fraction"); | |
printf("%-5s | %-10s | %-20s \n", buffer_sign, buffer_exp, buffer_fraction); | |
printf("\nFLOAT: S * 2^E * M\n\n"); | |
int sign = f.raw.sign ? -1 : 1; | |
printf("\tSign: S = (-1)^sign, 0 = Positive 1 = Negative\n"); | |
printf("\t\tsign = %d, (-1)^%d = %d => %s\n", | |
f.raw.sign, f.raw.sign, f.raw.sign, f.raw.sign ? "Negative" : "Positive"); | |
int exponent = f.raw.exponent - 127; | |
printf("\n\tExponent: E = e - Bias\n"); | |
printf("\t\te => %s = %d\n", buffer_exp, f.raw.exponent); | |
printf("\t\tBias => 2^(8-1) - 1 = 127\n"); | |
printf("\t\tE = %d - 127\n", f.raw.exponent); | |
printf("\t\tE = %d\n", f.raw.exponent - 127); | |
const int fraction_max = 1 << 23; | |
const double mantissa = ((double)(f.raw.fraction + fraction_max) / (double)fraction_max); | |
printf("\n\tMantissa: 1.f22f21...f1f0 = 1+f \n"); | |
printf("\t\tfraction max 2^23 = %d\n", 1 << 23); | |
printf("\t\tfraction = %d\n", f.raw.fraction); | |
printf("\t\tM = 1.0 + (%d/%d)\n", f.raw.fraction , fraction_max); | |
printf("\t\tM = %d/%d\n", f.raw.fraction + fraction_max, fraction_max); | |
printf("\t\tM = %lf\n", mantissa); | |
printf("\n\tResult: %d * (2^%d) * %lf \n", sign, exponent, mantissa); | |
printf("\t\t => %d * %lf * %lf\n", sign ,pow(2, exponent), mantissa); | |
printf("\t\t => %lf\n\n", sign*pow(2, exponent)* mantissa); | |
} | |
// DEC BINARY | |
// 0.5 => 0.1 => 1.0 * 2^(-1) SIGN=1 EXP=126 FRACTION = 00000 | |
// 123.45 | |
Float make_float(const char* in) | |
{ | |
printf("Float Input: %s\n", in); | |
Float result = { 0 }; | |
int exp = 0; | |
int index = 0; | |
bool found_dot = false; | |
char whole_number[50] = { 0 }; | |
char decimal_number[50] = { 0 }; | |
char buffer_whole_number_binary[33] = { 0 }; | |
int whole_number_len = 0; | |
char buffer_decimal_number_binary[33] = { 0 }; | |
int decimal_number_len = 0; | |
char buffer_result_binary[68] = { 0 }; | |
const char* pointer = in; | |
if (!is_digit(*pointer)) | |
{ | |
if (*pointer == '-') | |
{ | |
result.raw.sign = 1; | |
pointer++; | |
} | |
} | |
while (*pointer != '\0') | |
{ | |
if (*pointer == '.') | |
{ | |
pointer++; | |
found_dot = true; | |
index = 0; | |
continue; | |
} | |
else | |
{ | |
found_dot ? | |
(decimal_number[index] = *pointer) | |
: | |
(whole_number[index] = *pointer); | |
index++; | |
pointer++; | |
} | |
} | |
printf("whole number: %s\n", whole_number); | |
whole_number_len = string_dec_to_banary(whole_number, buffer_whole_number_binary); | |
printf("binary: %-20s\n", buffer_whole_number_binary); | |
printf("decimal number: %s\n", decimal_number); | |
decimal_number_len = string_decimal_dec_to_binary(decimal_number, buffer_decimal_number_binary); | |
printf("binary: %-20s\n", buffer_decimal_number_binary); | |
strncat(buffer_result_binary, buffer_whole_number_binary,33); | |
strncat(buffer_result_binary, ".",1); | |
strncat(buffer_result_binary, buffer_decimal_number_binary,33); | |
int move_count = 0; | |
bool move_to_left = true; | |
char* p = buffer_result_binary + whole_number_len; | |
if (whole_number_len > 1) | |
{ | |
move_count = whole_number_len - 1; | |
move_to_left = true; | |
} | |
else if (whole_number_len == 1) | |
{ | |
if (buffer_result_binary[0] == '1') | |
{ | |
move_count = 0; | |
} | |
else { | |
move_count = decimal_number_len + 1; | |
move_to_left = false; | |
} | |
} | |
int next = move_to_left ? -1 : 1; | |
for (int i = 0; i < move_count; i++) | |
{ | |
char temp = *(p + next); | |
*(p + next) = *(p); | |
*(p) = temp; | |
if (!move_to_left) | |
{ | |
if (*p == '1') | |
{ | |
remove_prefix_zero(buffer_result_binary); | |
break; | |
} | |
} | |
exp++; | |
p += next; | |
} | |
printf("exp: %d\n", exp * (move_to_left ? 1 : -1)); | |
printf("result: %-20s\n", buffer_result_binary); | |
printf("Fraction: %-20s\n", buffer_result_binary + 2); | |
printf("EXP: %d\n", exp + 127); | |
result.raw.exponent = exp + 127; | |
int flag = 1 << 22; | |
int fraction = 0; | |
char* fp = buffer_result_binary + 2; | |
while (*fp != '\0') | |
{ | |
if (*fp == '1') | |
{ | |
fraction |= flag; | |
} | |
flag >>= 1; | |
fp++; | |
} | |
result.raw.fraction = fraction; | |
return result; | |
} | |
int main() | |
{ | |
Float f = make_float("11.25555"); | |
dump_float((*(float*)&f)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment