Skip to content

Instantly share code, notes, and snippets.

@LucaXiang
Last active February 20, 2022 17:44
Show Gist options
  • Save LucaXiang/5f5d6dd07da01b471aedeaedc6d38016 to your computer and use it in GitHub Desktop.
Save LucaXiang/5f5d6dd07da01b471aedeaedc6d38016 to your computer and use it in GitHub Desktop.
#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