LenItsuki LenItsuki - 3 months ago 9
C Question

values changed by fscanf and fprintf for text file in C program

I would like to output like "correct output data" from "input data" by below C program. But the result shows that the values are changed like "actual output data". Let me know how to solve it.

input data

-5190.978 -90026.901 158.677 15 90 81 58

-5165.821 -90011.875 152.742 15 90 89 54

-5158.762 -90010.093 148.083 31 80 82 42


correct output data

-5190.978 -90026.901 158.677 90 81 58

-5165.821 -90011.875 152.742 90 89 54

-5158.762 -90010.093 148.083 80 82 42


actual output data

-5190.978 -90026.898 158.677 90 81 58

-5165.821 -90011.875 152.742 90 89 54

-5158.762 -90010.094 148.083 80 82 42


/***************************************************************************:::
xyz(ref)rgb2xyzrgb
19/08/2016
ver1.1 2009/3/7
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

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

FILE *fpr,*fpw;
int ref,r,g,b;
float x,y,z;
float n_x,n_y,n_z;

/*****************************************************
2.command line arguments processing
*******************************************************/
if(argc!=3)
{
fprintf(stderr,"Usage: %s (1)input_org.txt\n(2)write_xyz FILENAME\n",argv[0]);
exit(1);
}
printf("OPEN FILE NAME:%s\n",argv[1]);

/**********************************************************************************
**********************************************************************************
4. FILE OPEN + Binary File Input
**********************************************************************************
*************************************************************************************/

// open input file
if((fpr=fopen(argv[1],"rt"))==NULL)
{
printf("file cannot be opened。\n");
exit(1);
}

//write file
if((fpw=fopen(argv[2],"wt"))==NULL)
{
fprintf(stderr,"DSM by GSI data.raw\n");
exit(1);
}

while (fscanf(fpr,"%f %f %f %d %d %d %d", &x,&y,&z,&ref,&r,&g,&b) != EOF)
{
//printf("%.3f %.3f %.3f %d %d %d\n",x,y,z,r,g,b);
n_x = roundf(x * 1000) / 1000;
n_y = roundf(y * 1000) / 1000;
n_z = roundf(z * 1000) / 1000;
//printf("%.3f %.3f %.3f %d %d %d\n",n_x,n_y,n_z,r,g,b);
fprintf(fpw,"%.3f %.3f %.3f %d %d %d\n",n_x,n_y,n_z,r,g,b);
//printf("x:%f y:%f z:%f\n", x,y,z);
}

fclose(fpr);
fclose(fpw);

}

Answer

Instead of -90026.901 computer stores the nearest number that fits the precision. It's 90026.898. Remember that numbers are stored in binary on computers and 901/1000 doesn't have finite binary form. For this reason, some of the precision will be cut.

It would be the same if you tried to print 1/3. It won't print all the digits, but you actually expect it as you're used to decimal system. In binary system, some of the fractions that have finite decimal form won't have one.

The solution? Always try to enlarge macheps which is the arithmetic precision. The easiest would be to use double instead of float. It still doesn't give 100% but it's more probable that will work.

The topic is known as scientific calculation and is pain in a** for programmers.

Comments