Hi, and forgive me for posting c++ code here, but I think most of you were ( or are working now as ) c++ programmers.

I have a function which should do double rounding correctly, but there are some pitfalls and I need help from those who might have been stumbled in the same manner as I am now.

Here's a piece of code which does the rounding from precision 3 to 2.

Several bad numbers are 1.005 and 1.015 which are rounded to 1 and 1.01 respectedly. There are much more of them.

``````#include <stdlib.h>
#include <stdio.h>
#include <math.h>

double RoundDouble(double doValue, int nPrecision)
{
static const double doBase = 10.0;
double doComplete5, doComplete5i;

doComplete5 = doValue * pow(doBase, (double) (nPrecision + 1));

if(doValue < 0.0)
doComplete5 -= 5.0;
else
doComplete5 += 5.0;

doComplete5 /= doBase;
modf(doComplete5, &doComplete5i);

return doComplete5i / pow(doBase, (double) nPrecision);
}

void kkk()
{
}

int main()
{

double testFloatNrPrec2 = 0.0;

for ( int i5=0; i5 < 10; i5++ )
for ( int i4=0; i4 < 10; i4++ )
for ( int i3=0; i3 < 10; i3++ )
for ( int i2=0; i2 < 10; i2++ )
for ( int i1=0; i1 < 10; i1++ )
{
int id = i5*10000 + i4*1000 + i3*100 + i2*10 + i1;

if ( id == 1005 )
{
kkk(); //place your breakpoint here and watch for rounding problem...
}

double _value = i5*10 + i4;

double _multiplier = 1.;
_multiplier /= 10;
_value += i3*_multiplier;
_multiplier /= 10;
_value += i2*_multiplier;
_multiplier /= 10;
_value += i1*_multiplier;

if (( i1 % 5 == 0 ) && ( i1 % 10 != 0 )) testFloatNrPrec2 += 0.01;

double rndtest = RoundDouble ( _value, 2 );
double testres = _value - rndtest;

printf( "%06ld %g --> %g --> %g\n", id, _value, rndtest, testres );
}
return 0;
}``````
Posted on 2004-10-19 09:10:54 by Ulterior
Look at the binary representation - many decimal numbers can not be represented by a finite number of binary bits. There are two ways around this problem: maintain highest percision for as long as possible, or keep everything as decimal (BCD).

Spreadsheets typically have a decimal format for bookkeeping to prevent rounding errors. Databases also have a decimal format. Ketil (RadASM author) has also created a BCD library.

Posted on 2004-10-19 10:23:14 by bitRAKE