473,322 Members | 1,671 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Re: Rounding error when converting from double to int

Victor said:
Also, consider that *all calculations* should be performed in *cents* and not in
dollars. You should never have to "round" anything like '1.115'.
The double value that I'm trying to convert to GCSMoney (which is
implemented as cents) was produced by multiplying a dollar amount by
an interest rate to get interest.

double amount = 126.60;
double interestRate = .075;
double interest = amount * interestRate;
int interestAsCents = interest * 100.0 + 0.5;

The debugger says interest = 9.495.
But when I convert it to cents, we see that interest really wasn't
9.495 since the cents rounds to 949 instead of 950.

Below is code where I do my calculations as cents. I can convert
amount to cents by multiplying by 100 since I'm dealing with a dollar
amount. But interest rate is not a dollar amount. I can't convert it
to cents. In this particular case, I can convert it to an integer by
multiplying by 1000 since it has three decimal places.

double amount = 126.60;
double interestRate = .075;
int amountAsCents = amount * 100; // = 12660
int interestRateAsInt = interestRate * 1000; // = 75
int interestTemp = amountAsCents * interestRateAsInt; // = 949500
interestTemp += 500; // round it. = 950000
int interestAsCents = interestTemp / 1000; // undo interestRate
* 10000. = 950

So this works. But what if I have an interest rate that has more
decimal places? For example, 0.1234? Then I would have to convert
it to an int by multiplying by 10000 and later divide by 10000.

In general, if I had a money class that stored money amounts as cents
and I needed a multiplication operator that could multiply a money
type by a double, how would I implement that? Would I just
arbitrarily choose the amount of double precision like this?:

Clint
int precision = 3;
double amount = 126.60;
double interestRate = .075;
int amountAsCents = amount * 100; // = 12660
int interestRateAsInt = interestRate * pow( 10.0, precision ); //
= 75
int interestTemp = amountAsCents * interestRateAsInt; // = 949500
interestTemp += 5 * pow(10.0, precision - 1 ); // round it. = 950000
int interestAsCents = interestTemp / pow(10.0, precision); //
undo interestRate * 10000. = 950

Or instead of hardcoding the precision in the code above, could I
detect how many decimal places there are and use that as my precision?


Jun 27 '08 #1
2 5050
On May 27, 11:57 pm, clintonb <cba...@centurytel.netwrote:
Victor said:
Also, consider that *all calculations* should be performed
in *cents* and not in dollars. You should never have to
"round" anything like '1.115'.
The double value that I'm trying to convert to GCSMoney (which is
implemented as cents) was produced by multiplying a dollar amount by
an interest rate to get interest.
double amount = 126.60;
double interestRate = .075;
double interest = amount * interestRate;
int interestAsCents = interest * 100.0 + 0.5;
The debugger says interest = 9.495.
But when I convert it to cents, we see that interest really
wasn't 9.495 since the cents rounds to 949 instead of 950.
Well, the first error in the above: interestRate is NOT .075,
because .075 can't be represented as a double. Since you start
with an incorrect value, obviously, all of the remaining values
will be incorrect as well.
Below is code where I do my calculations as cents. I can
convert amount to cents by multiplying by 100 since I'm
dealing with a dollar amount. But interest rate is not a
dollar amount. I can't convert it to cents.
No, but it has been specified as an exact decimal fraction, so
you must use some representation which preserves its exact
value, and double isn't it.

(The actually depends on what you're using the monetary values
for. But if it's any bookkeeping, the law generally says
exactly how you have to round, and it it almost always specifies
the rules in terms of decimal values.)
In this particular case, I can convert it to an integer by
multiplying by 1000 since it has three decimal places.
For example. More generally, regardless of the number of
decimal places, you can convert by multiplying by a power of
ten.

This is usually handled with some sort of class, which stores
the integral value and the number of digits after the decimal.
The values are determined directly when converting the input.
double amount = 126.60;
double interestRate = .075;
int amountAsCents = amount * 100; // = 12660
int interestRateAsInt = interestRate * 1000; // = 75
int interestTemp = amountAsCents * interestRateAsInt; // = 949500
interestTemp += 500; // round it. = 950000
int interestAsCents = interestTemp / 1000; // undo interestRate
* 10000. = 950
So this works. But what if I have an interest rate that has
more decimal places? For example, 0.1234? Then I would have
to convert it to an int by multiplying by 10000 and later
divide by 10000.
Given something like:

class Decimal
{
// ...
long long value ;
int scalingFactor ;
} ;

you multiply by multiplying the value, and adding teh
scalingFactor.

In addition to the usual arithmetic operations, you probably
want some functions to round to a specific position, etc.
In general, if I had a money class that stored money amounts
as cents and I needed a multiplication operator that could
multiply a money type by a double, how would I implement that?
Would I just arbitrarily choose the amount of double precision
like this?:
No. Not arbitrarily, but from the input. If the input is 1.23,
then value is 123, and scalingFactor 2. If it is 0.12345, then
value is 12345, and scalingFactor 5.
Clint
int precision = 3;
double amount = 126.60;
double interestRate = .075;
int amountAsCents = amount * 100; // = 12660
int interestRateAsInt = interestRate * pow( 10.0, precision ); //
= 75
int interestTemp = amountAsCents * interestRateAsInt; // = 949500
interestTemp += 5 * pow(10.0, precision - 1 ); // round it. = 950000
int interestAsCents = interestTemp / pow(10.0, precision); //
undo interestRate * 10000. = 950
Or instead of hardcoding the precision in the code above,
could I detect how many decimal places there are and use that
as my precision?
Exactly. And since the only powers you need are those of 10
(and you can probably restrict those, e.g. by restricting the
scalingFactor to +/- 13, like Cobol does), you can easily put
those in a table. (Don't forget that pow(10.0, precision) will
return a possibly inexact double.)

Better yet, I'm sure that there are packages on the market which
do this already. Use one of them.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 27 '08 #2
On 2008-05-27 23:57, clintonb wrote:
Victor said:
>Also, consider that *all calculations* should be performed in *cents* and not in
dollars. You should never have to "round" anything like '1.115'.

The double value that I'm trying to convert to GCSMoney (which is
implemented as cents) was produced by multiplying a dollar amount by
an interest rate to get interest.

You should perform the calculations with integers too, as soon as you
use floating point values you run the risk of getting problems. You
should consider creating (or getting from somewhere) a Decimal-class
which can represent decimal numbers and perform calculations with them.

--
Erik Wikström
Jun 27 '08 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Ken Allen | last post by:
Recently I placed a number of files that I am developing with .Net under VSS control. Ever since that time I am getting an odd error when I double-click on one or more of the files: An error...
1
by: mdawoodk | last post by:
i am getting error "input string was not in correct format" when converting a string decimal into integer value. code is like this: string strVal = ""; int nVal = 0; strVal = "14.9"; nVal...
13
by: Shirsoft | last post by:
I have a 32 bit intel and 64 bit AMD machine. There is a rounding error in the 8th digit. Unfortunately because of the algorithm we use, the errors percolate into higher digits. C++ code is...
1
by: Anandshr | last post by:
I have a database created in Ms Access 95 file format. now i want to convert it into Ms Access 2000,2002 or 2007 file format. I got the error when converting that database. I've already tried to...
1
Bob Ross
by: Bob Ross | last post by:
I have a vb.net 2.0 website and I am trying to change it to a web application. I have followed these instructions here - http://webproject.scottgu.com/VisualBasic/Migration2/Migration2.aspx up to...
0
by: =?ISO-8859-1?Q?Marcel_M=FCller?= | last post by:
clintonb wrote: There is nothing like an original double amount. If you care about rounding errors you must not store any currency value in an approximate number. You must not do this even once....
4
by: simulationguy | last post by:
I inherited an Access 2003 database runs fine in 2003 but in 2007 I get an error on updating a form. Record Not available on the last statement !ItemNumber.SetFocus Does anyone know why...
2
by: Alan Adolphe | last post by:
Hi, I have converted C# code to vb.net using the online converter tools. One error messages I can't seem to figure out. Any ideas or help is appreciated. Public Sub New() ...
0
by: Treesa Franco | last post by:
I wanted to convert an aspx page contents to PDF.I am using iText in my project. While running i encountered the following problems.Can anyone help? Server Error in '/' Application. Font size...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.