Slightly inaccurate results when converting binary floating point numbers to decimal

What should he do: Example input - 101.101 output - 5.625

This is how I wrote the binary decimal floating point converter, but there is a slight error - the problem is that the output does not match the correct decimal point.

What my code does: Input - 101.101 Output - 5.624985

What my code does when I change the count from -16 to -32:

Entrance - 101.101 Exit - 5.625000 Correct.

Input - 101.111 Output - 5.875061 It is still off, it should be 5.875

#include <stdio.h>

double decimal(double decpart);
long int integer(long int intpart);

int main(int argc, const char * argv[])
{

    double x;
    scanf("%lf", &x);
    long int intpart = (long int)x;
    double decpart = x-intpart;

    double finint = integer(intpart);
    double findec = decimal(decpart);

    double finnum = findec + finint;
    printf("%lf\n",finnum);

    return 0;
}

long int integer(long int intpart)
{
    double sum = 0;
    long int a, b, p= 0;

while(intpart>0)
{
    a = intpart % 10;
    b = a*(pow(2, p));
    sum = sum + b;
    p++;
    intpart = intpart / 10;
}
    return sum;
}

double decimal(double decpart)
{
    double sum = 0;
    int count = 0;
    while (decpart > 0 && count > -32)
    {
        count--;
        decpart = decpart*10;
        if (decpart >= 1)
        {
            decpart = decpart - 1;
            sum = sum + pow(2, count);
        }
    }

    return sum;
}
+4
source share
5 answers

- , pow, , . , pow(x, y) exp(log(x) * y), log exp 2.718281828.... , , , 2, log(2) - , exp(log(2)) .

count pow double value, 0.5 0.5 :

double decimal(double decpart)
{
    double sum = 0;
    double value = 0.5;
    while (decpart > 0 && value > 1.0e-5) // approx. 2 ^ -16
    {
        decpart = decpart*10;
        printf("%lf\n",decpart);
        if (decpart > 1)
        {
            decpart = decpart - 1;
            sum = sum + value;
        }
        value *= 0.5;
    }

    return sum;
}

, , pow. , IEEE-754 ( ), value , .


, , scanf double , , 0,1, . char, .

+2

-16, 1 65 536 (0.0000153...). , , . , , -32 -53. ( ln2(DBL_EPSILON)) -

[Edit2] -17, -18 .. . . .

if (decpart > 1)if (decpart >= 1).


[]

C DBL_MIN_10_EXP -37 pow(2, count) count int -80 +80.

FP, , N ( "101.101" - 6). N - 1/DBL_EPSILON 8 9 . , @Drew McGowen .

[Edit2]

double N 16 17. , while (decpart > 0 && count > -16). , FP "101.111" ( 101.111000000000004...) , 101.111000000000001111111...

( 101 + 1 * 1/2 + 1 * 1/4 + 1 * 1/8 + 1 * pow (2, -15) + 1 * pow (2, -16)))... = 5.875061

..... decimal() , log10(1/DBL_EPSILON) 15,16 , . 16 1 65 536 (0,000015...). , , (, @Drew McGowen, @BLUEPIXY).

double BinaryFloatinPoint(const char *s) {
  double sum = 0.0;
  double power = 1.0;
  char dp = '.';  // binary radix point
  while (*s) {
    if (*s == '0' || *s == '1') {
      sum *= 2.0;
      sum += *s - '0';
      power *= 0.5;
    } else if (*s == dp) {
      dp = '0';
      power = 1.0;
    } else {
      return 0.0; // Unexpected char, maybe return NAN instead
    }
    s++;
  }
  if (dp == '0') {  // If dp found ...
    sum *= power;
  }
  return sum;
}
+2

, , 0.1 (10), .
.

#include <stdio.h>
#include <string.h>

double bstrtod(const char *bstr){
    double x = 0, one = 1.0;
    char *p = strchr(bstr, '.');
    if(p){
        char *fp = p;
        while(*++fp){
            one /= 2.0;
            if(*fp=='1')
                x += one;
        }
    } else {
        p = strchr(bstr, '\0');
    }
    one = 1.0;
    do{
        if(*--p == '1')
            x += one;
        one *= 2.0;
    }while(p!=bstr);

    return x;
}

int main(void){
    double x = bstrtod("101.101");
    printf("%f\n", x);//5.625000
    return 0;
}
+2

This error occurs due to rounding errors. Even if you enter 8, it actually stores 7.99999 ... That's why the problem arises.

0
source

Precise binary to decimal converter

This code uses strings to convert binary input to decimal output

#include <stdio.h>
#include <string.h>

double blembo(const char *blem);

int main(void)
{
    char input[50];
    gets(input);

    int t = 0, flag = 0;
    while (input[t] != '\0')  // This whole block of code invalidates "hello" or "921" or "1.1.0" inputs
    {
        if(input[t] == '0' || input[t] == '1' || input[t] == '.')
        {
            if(input[t] == '.')
            {
                if(flag != 1)
                {
                    flag = 1;
                    t++;
                    continue;
                }
                else
                {
                    printf("\nIncorrect input\n");
                    return 0;
                }
            }
            else
            {
                t++;
                continue;
            }
        }
        else
        {
            printf("\nIncorrect input\n");
            return 0;
        }
    }

    double output = blembo(input);
    printf("%lf\n", output);
    return 0;
}

double blembo (const char *blem)
{
    double x=0, one = 1.0;
    char *p , *fp;
    p = strchr(blem, '.');
    if(p)
    {
        fp = p;
        while(*++fp)
        {
            one = one / 2.0;
            if(*fp == '1')
            {
                x = x + one;
            }
        }
    }
        else
        {
            p = strchr(blem, '\0');
        }

    one = 1.0;
    do
    {
        if(*--p == '1')
        {
            x = x + one;
        }

        one = one * 2.0;
    }
    while(p!=blem);

    return x;
}
0
source

All Articles