PDA

View Full Version : Banker's rounding



matheww
25th June 2007, 04:03
Hi..

Its irking me, as I have not found a simple solution. I am writing an application that requires banker's rounding, so the round function is useless..

basicaly i need to be able to round to either 2 or 4 decimal places using bankers rounding..

eg

double a = 107.10;
double b = bankersrounding(a / 12.0,2);

b should equal 8.93, not 8.925 or 9 or 8..

also a value of 8.935 rounded to 2dp should be 8.94

Any ideas on a simple function or of QT actually implements this - or some form of decimal currency type that handles this automatically?

Ta.
Mathew.

sunil.thaha
25th June 2007, 04:34
I hope this would do



double round( double value, int precision ){
return long( value * pow(10, precision) + 0.5 )/ pow(10, precision ) ;
}

matheww
25th June 2007, 04:53
thanks, its close

but an input of 8.925 still return 8.92 where as i need 8.93
(this might sound strange but if i have a carton that I buy at 107.10 and it has 12 bags inside, 107.10 / 12 = 8.925 and i have a 25% markup, then the carton is sold at 107.10 + 25% and the bag should be sold at 8.93 + 25% which = 11.90 not 11.89 (which i would loose 12c per carton * 1000 cartons per year :eek: )

If i calculate inside the database (postgresql) using its round function I get the expected (right) results and its their round function i need to emulate..

sunil.thaha
25th June 2007, 05:04
but an input of 8.925 still return 8.92 where as i need 8.93


you will get exactly that, all you have to do is to try it out :p
round( 8.925, 2 ); and see what you get

matheww
25th June 2007, 09:00
you will get exactly that, all you have to do is to try it out :p
round( 8.925, 2 ); and see what you get

from the debug..

value = 8.925 result = 8.92
the function..


double bankround(double value, int precision = 2){
double rv = long( value * pow(10, precision) + 0.5 )/ pow(10, precision );
qDebug() << "value = " << value << " result = " << rv;
return rv ;
}

sunil.thaha
25th June 2007, 09:10
OMG !!

I am getting 8.93 on g++ 3.4.4 (linux ) and g++ (GCC) 3.4.2 (mingw-special) Windows

matheww
25th June 2007, 09:24
got me puzzled..

g++ -v
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.2 20070502 (Red Hat 4.1.2-12)

I am using fedora core 7 x86_64

wysota
25th June 2007, 10:08
.5 might actually be .49999999999999 on 64b so after flooring this will be 0 :) Try changing the datatype (for instance to float).

BTW. For banking (or similar) you should use high precision math, for example one of these:
http://www.tc.umn.edu/~ringx004/article-main.html
http://www.nongnu.org/hpalib/
http://gmplib.org/

matheww
25th June 2007, 22:03
.5 might actually be .49999999999999 on 64b so after flooring this will be 0 :) Try changing the datatype (for instance to float).

You are right there - have been programming so long in Delphi using their Currency type that I forgot that doubles (and floats) can be a bit inaccurate, I changed the function parameter and return value to floats and i get a correct result.


BTW. For banking (or similar) you should use high precision math, for example one of these:
http://www.tc.umn.edu/~ringx004/article-main.html
http://www.nongnu.org/hpalib/
http://gmplib.org/

I will have a look at these.. really need something similar to the pascal currency type...

jacek
25th June 2007, 22:22
really need something similar to the pascal currency type...
See this: http://quantlib.org/