1
#include "ieee754.h" #include <stdio.h> #include <math.h> //This program convert a floating number to its binary representation (IEEE754) in computer memory int main() { long double f, binaryTotal, binaryFrac = 0.0, frac, fracFractor = 0.1; long int integer, binaryInt = 0; long int p = 0, rem, temp; printf("\nEnter floating number: "); scanf("%Lf", &f); //separate the integer part from the input floating number integer = (int)f; //separate the fractional part from the input floating number frac = f - integer; //loop to convert integer part to binary while (integer != 0) { rem = integer % 2; binaryInt = binaryInt + rem *pow(10, p); integer = integer / 2; p++; } //loop to convert fractional part to binary while (frac != 0) { frac = frac * 2; temp = frac; binaryFrac = binaryFrac + fracFractor * temp; if (temp == 1) frac = frac - temp; fracFractor = fracFractor / 10; } binaryTotal = binaryInt + binaryFrac; printf("binary equivalent = %Lf\n", binaryTotal); } 

I'm trying to convert floating number to binary representation (64-bit). This code is working but not perfect. For example, when I convert .575 it gives me 0.100100 but when I do the conversion using this website http://www.exploringbinary.com/floating-point-converter/, the right output should be 0.1001001100110011001100110011001100110011001100110011

I am having trouble understanding what makes my code truncate the number. Could anyone help me how to fix it? I appreciate your help.

7
  • Compile with all warnings enabled. Commented Oct 17, 2016 at 7:44
  • @MichaelWalz there is no warning: ideone.com/aIShip Commented Oct 17, 2016 at 7:47
  • 1
    @mike you should write how much digits you want after the .: "%.20Lf" will print 0.10010011001100110011. Commented Oct 17, 2016 at 7:50
  • @mike mch is right, my comment is not really relevant here. Commented Oct 17, 2016 at 7:56
  • 1
    That's because the number is not exactly representable in binary (or double). So it can only print the nearest number, which can be saved in a long double. You should save your number into a string. Commented Oct 17, 2016 at 8:18

2 Answers 2

3

Many problems:

  1. Using (int) to extract the integer portion of a long double severely limits the range. Use modfl(long double value, long double *iptr);

    long double f; long int integer; //separate the integer part from the input floating number // Weak code integer = (int)f; long double ipart; long double fpart = modfl(f, &ipart); 
  2. long p; pow(10,p); --> loss of precision in pow() return value once p exceeds some value, (example 25). Also strange to use pow() with a function that employs long double. I'd expect powl().

  3. Various other inexact FP issues: fracFractor/10, limited precision of long.

Code is strange as it attempts to convert a FP number (likely in some binary format) into a binary representation. It should not require 10 anywhere in the code.

Suggest something simple like

#include<stdio.h> #include<stdlib.h> #include<math.h> #include<float.h> static void print_ipart(long double x) { int digit = (int) (modfl(x/2, &x)*2.0) + '0'; if (x) { print_ipart(x); } putchar(digit); } void print_bin(long double x) { // Some TBD code // Handle NAN with isnan() // Handle infinity with isfinite() putchar(signbit(x) ? '-' : '+'); long double ipart; long double fpart = modfl(fabsl(x), &ipart); print_ipart(ipart); putchar('.'); while (fpart) { long double ipart; fpart = modfl(fpart * 2, &ipart); putchar((int)ipart + '0'); } putchar('\n'); } int main() { print_bin(-4.25); print_bin(.575); print_bin(DBL_MAX); print_bin(DBL_MIN); print_bin(DBL_TRUE_MIN); } 

Output

-100.01 +0.1001001100110011001100110011001100110011001100110011001100110011 +1111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000. +0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your help! This is a very sophisticated way to write. Little beyond my current familiarity with C though.. could you explain how (modfl(x/2, &x)*2.0) + '0' works? I found that modfl separate intpart from fracpart, and I see the use of dividing 2. I guess my questions are what does &x does and why are you multiplying it by 2? and are you putting '0' in the end when x%2 is 0? I thought this converter project would be a good practice to write C code but it's little beyond my understanding right now.. I appreciate your help
@mike &x is the address of x. modfl(lf, addr) breaks lf into a fraction part, which is returned and a whole number part, which is saved at the address discussed. The function result is a fraction, in this code, it will be 0.0 or 0.5. Multiplying by 2 makes that 0.0 or 1.0. Adding that to '0' makes '0' or '1' for printing. Hopefully this approach is simpler than your original. I do not think it is beyond your understanding.
Ah okay it's clear now. Thank you very much for your kindness.
0

Here's why this is unlikely to work:

fracFractor = 0.1 ... fracFractor = fracFractor/10 

0.1 can't be represented accurately in any binary floating point format. You can't represent 0.1 as a multiple of negative powers of two. Dividing it by 10 will have it gather rounding errors at every step. It may be that you got this loop to actually exit because you do end up comparing a repeating fraction to another repeating fraction.

And this will severely limit what you can achieve:

binaryTotal = binaryInt + binaryFrac; 

Doing this in floating point will have serious limitations - not in the least that representing 0.1 is not representable as described above. That's why you get answers that appear as a mix of binary and decimal digits.

To solve this, you should probably look at the individual bits of the number. To keep the overall idea of your solution intact, the easiest will be to keep subtracting a negative power of two (0.5, 0.25, etc.) from your fraction, test if it's still positive, and build a string based on that. Then use similar logic for the integer part.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.