473,851 Members | 2,164 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 interestRateAsI nt = interestRate * 1000; // = 75
int interestTemp = amountAsCents * interestRateAsI nt; // = 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 interestRateAsI nt = interestRate * pow( 10.0, precision ); //
= 75
int interestTemp = amountAsCents * interestRateAsI nt; // = 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 5136
On May 27, 11:57 pm, clintonb <cba...@century tel.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 interestRateAsI nt = interestRate * 1000; // = 75
int interestTemp = amountAsCents * interestRateAsI nt; // = 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 interestRateAsI nt = interestRate * pow( 10.0, precision ); //
= 75
int interestTemp = amountAsCents * interestRateAsI nt; // = 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 objektorientier ter Datenverarbeitu ng
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
1064
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 occurred while loading the document. Fix the error, and then try loading the document again. The error message follows: Unspecified error. Does anyone have any idea what may be causing this problem? -Ken
1
9986
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 += Convert.toInt32(strVal);
13
6199
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 ------------------ b += (float)(mode *val); On 32 bit(intel , vs 2003, C++), some watch variables are
1
1507
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 convert the process given in Ms Access. It didn't worked. What may be the next process to convert it?
1
1142
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 the end of step 4. but at this point I get an error for every control on every page - Error 46 'SelectOrderLabel' is already declared as 'Protected Dim WithEvents SelectOrderLabel As System.Web.UI.WebControls.Label' in this class. Does...
0
287
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. Least of all at something like an original value. If you take account of that the question to do a correct back-conversion is obsolete. Of course, if you make some assumptions about the expected values and the domain of the values a conversion...
4
1719
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 Access 2007 is different and any clues on how to get it to work? With Forms!frmMain!frmSKUInput.Form !WhichSKUCombo.Value = "" !WhichSKUList.Value = "" .RecordSource = strSQL1
2
3456
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() InitializeComponent() Me.Flip1Half.Completed += New EventHandler(AddressOf Flip1Half_Completed) End Sub
0
1974
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 too small: 0 Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details:...
0
9897
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
11019
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10670
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10728
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7906
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5736
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5933
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4549
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4143
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.