473,396 Members | 2,036 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,396 software developers and data experts.

(float / double)

Hello,
I have a basic question related to datatypes.
I am trying to read a value using Microsoft's ADO recordset from a
field (lets call it 'Price') with datatype decimal(19,6) => 19 =
Precision, 6 = Scale
1) When I read this field into float datatype. I get a value 1.9000,
which is correct. But when I read its value in a double datatype I get
1.8999999761581.
2) My second question is related to multiplication.
Should it cause any problem?

dblPrice =1.23333;
Amount = 91000000;
PricedAmount= dblPrice * Amount
PricedAmountshould have 112233030

But i am getting 112230300 (thus I am loosing precision).

Here is the implementation of Multiplication operator of CCurrency
class

CCurrency CCurrency::operator*(float nOperand) const
{
if (!GetStatus() == valid)
return *this;
CCurrency curOperand;
VarCyFromR4(nOperand,&curOperand.m_cur);
CCurrency curResult;
HRESULT hr = VarCyMul(*this, curOperand,&curResult.m_cur);
if FAILED(hr)
{
curResult.SetStatus(invalid);
curResult.m_cur.int64 = 0;
}
return curResult;
}

CCurrency CCurrency::operator*(double nOperand) const
{
if (!GetStatus() == valid)
return *this;
CCurrency curOperand;
VarCyFromR8(nOperand,&curOperand.m_cur);
CCurrency curResult;
HRESULT hr = VarCyMul(*this, curOperand,&curResult.m_cur);
if FAILED(hr)
{
curResult.SetStatus(invalid);
curResult.m_cur.int64 = 0;
}
return curResult;
}

Mar 4 '06 #1
8 5421
On 4 Mar 2006 07:36:39 -0800, ab**********@hotmail.com wrote:
Hello,
I have a basic question related to datatypes.
I am trying to read a value using Microsoft's ADO recordset from a
field (lets call it 'Price') with datatype decimal(19,6) => 19 =
Precision, 6 = Scale
1) When I read this field into float datatype. I get a value 1.9000,
which is correct. But when I read its value in a double datatype I get
1.8999999761581.
DECIMAL is a fixed-point numeric type, and such numbers often cannot
be expressed exactly as a floating-point number in a computer. For
example, 1.5 can be stored exactly with no loss of precision because
0.5 is equivalent to 1/2 which is 0.1 in binary notation. Similarly,
any other number which can be expressed as the sum of various powers
of 2 can be represented exactly. But not 1/10, for example, and not
9/10.

The float value *appears* to be exactly the same as the number in the
database. In reality, the ODBC driver has rounded the value for you.
The double has more precision, so you see the effects of the rounding
errors between decimal and floating-point types.
2) My second question is related to multiplication.
Should it cause any problem?

dblPrice =1.23333;
Amount = 91000000;
PricedAmount= dblPrice * Amount
PricedAmountshould have 112233030

But i am getting 112230300 (thus I am loosing precision).
Obviously.
Here is the implementation of Multiplication operator of CCurrency
class

CCurrency CCurrency::operator*(float nOperand) const
{
if (!GetStatus() == valid)
return *this;
CCurrency curOperand;
VarCyFromR4(nOperand,&curOperand.m_cur);
CCurrency curResult;
HRESULT hr = VarCyMul(*this, curOperand,&curResult.m_cur);
if FAILED(hr)
{
curResult.SetStatus(invalid);
curResult.m_cur.int64 = 0;
}
return curResult;
}

CCurrency CCurrency::operator*(double nOperand) const
{
if (!GetStatus() == valid)
return *this;
CCurrency curOperand;
VarCyFromR8(nOperand,&curOperand.m_cur);
CCurrency curResult;
HRESULT hr = VarCyMul(*this, curOperand,&curResult.m_cur);
if FAILED(hr)
{
curResult.SetStatus(invalid);
curResult.m_cur.int64 = 0;
}
return curResult;
}


My suggestion would be to implement CCurrency as a decimal scaled
integer value (i.e., use long long if you have it, else __int64) and
not as a double. That way, you avoid the rounding problems.

But how many digits will you need? Do any of the values in the
database exceed INT64_MAX scaled to a precision of 6? If so, you'll
need to either look for a third-party solution or implement one
yourself.

--
Bob Hairgrove
No**********@Home.com
Mar 4 '06 #2
ab**********@hotmail.com wrote:
I have a basic question related to datatypes.
I am trying to read a value using Microsoft's ADO recordset from a
field (lets call it 'Price') with datatype decimal(19,6) => 19 =
Precision, 6 = Scale
1) When I read this field into float datatype. I get a value 1.9000,
which is correct. But when I read its value in a double datatype I get
1.8999999761581.
Do you know how those numbers (19 and 6) relate to the significant
digits and the range of the number? Since MS ADO "recordset" is not
defined in C++, you have to tell us. Then together we can think why
you see what you see.
2) My second question is related to multiplication.
Should it cause any problem?

dblPrice =1.23333;
Amount = 91000000;
PricedAmount= dblPrice * Amount
PricedAmountshould have 112233030

But i am getting 112230300 (thus I am loosing precision).
"Losing". Well, how are 'dblPrice' and 'Amount' declared? Hos is
'PricedAmount' declared?
Here is the implementation of Multiplication operator of CCurrency
class
[..]


How is this relevant to your questions?

If you need an industrial-strength system for handling money, you
should _not_ use 'float' or even 'double'. You should implement
your own numeric representation based most likely on fixed-point
arithmetic with something like 5 digits after the decimal point.

Look on the web for 'fixed-point arithmetic' and you shall find.

V
--
Please remove capital As from my address when replying by mail
Mar 4 '06 #3
Amount & PricedAmount are objects of CCurrency class (implementation is
part of my own project).

dblPrice is declared as double.

Implementation of CCurrency is as follows
---
class CCurrency
{
// Constructors
public:
CCurrency();
CCurrency(CURRENCY cySrc);
CCurrency(const CCurrency& curSrc);
CCurrency(const _variant_t & varSrc);
CCurrency(long nUnits, long nFractionalUnits);
CCurrency(__int64 int64Value);
// Attributes
public:
enum CCurrencyStatus
{
valid = 0,
invalid = 1, // Invalid currency (overflow, div 0, etc.)
null = 2, // Literally has no value
};
CURRENCY m_cur;
CCurrencyStatus m_status;
void SetStatus(CCurrencyStatus status);
CCurrencyStatus GetStatus() const;
// Operations
public:

const CCurrency& operator=(CURRENCY cySrc);
const CCurrency& operator=(const CCurrency& curSrc);
const CCurrency& operator=(const _variant_t & varSrc);

BOOL operator==(const CCurrency& cur) const;
BOOL operator!=(const CCurrency& cur) const;
BOOL operator<(const CCurrency& cur) const;
BOOL operator>(const CCurrency& cur) const;
BOOL operator<=(const CCurrency& cur) const;
BOOL operator>=(const CCurrency& cur) const;

// CCurrency math
CCurrency operator+(const CCurrency& cur) const;
CCurrency operator-(const CCurrency& cur) const;
const CCurrency& operator+=(const CCurrency& cur);
const CCurrency& operator-=(const CCurrency& cur);
CCurrency operator-() const;

CCurrency operator*(const CCurrency& cur) const;

CCurrency operator*(long nOperand) const;
CCurrency operator*(float nOperand) const;
CCurrency operator*(double nOperand) const;
CCurrency operator/(long nOperand) const;
CCurrency operator/(float nOperand) const;
CCurrency operator/(double nOperand) const;

const CCurrency& operator*=(long nOperand);
const CCurrency& operator/=(long nOperand);
const CCurrency& operator*=(float nOperand);
const CCurrency& operator/=(float nOperand);
const CCurrency& operator*=(double nOperand);
const CCurrency& operator/=(double nOperand);

operator CURRENCY() const;
operator _variant_t() const;

// CCurrency definition
void SetCurrency(long nUnits, long nFractionalUnits);
CCurrency Absolute();
};
---
Victor Bazarov wrote:
ab**********@hotmail.com wrote:
I have a basic question related to datatypes.
I am trying to read a value using Microsoft's ADO recordset from a
field (lets call it 'Price') with datatype decimal(19,6) => 19 =
Precision, 6 = Scale
1) When I read this field into float datatype. I get a value 1.9000,
which is correct. But when I read its value in a double datatype I get
1.8999999761581.


Do you know how those numbers (19 and 6) relate to the significant
digits and the range of the number? Since MS ADO "recordset" is not
defined in C++, you have to tell us. Then together we can think why
you see what you see.
2) My second question is related to multiplication.
Should it cause any problem?

dblPrice =1.23333;
Amount = 91000000;
PricedAmount= dblPrice * Amount
PricedAmountshould have 112233030

But i am getting 112230300 (thus I am loosing precision).


"Losing". Well, how are 'dblPrice' and 'Amount' declared? Hos is
'PricedAmount' declared?
Here is the implementation of Multiplication operator of CCurrency
class
[..]


How is this relevant to your questions?

If you need an industrial-strength system for handling money, you
should _not_ use 'float' or even 'double'. You should implement
your own numeric representation based most likely on fixed-point
arithmetic with something like 5 digits after the decimal point.

Look on the web for 'fixed-point arithmetic' and you shall find.

V
--
Please remove capital As from my address when replying by mail


Mar 5 '06 #4
Hello,
I am working on a program written by someone else and facing problems
in precisions due to usage of floating point date types. My input is
are the values in the rows of database (MS SQL Server) where fixed
point datatypes are used to store input as well as result e.g.
decimal(16,6) & money.

As the end I end up only using precision of 4 decimal instead of 6.

dblPrice =1.23333;
Amount = 91000000;
PricedAmount= dblPrice * Amount
PricedAmountshould have 112233030

But i am getting 112230300 (thus I am loosing precision).

dblPrice is declared as double
PricedAmount and Amount are objects of CCurrency

Here is the implementation of Multiplication operator of CCurrency
class and declaration of CCurrency

Any help to make this program more robust for more real implementation.

I have started to consider writign a class for fixed point arithmatic
datatype. Please let me know if it is a good start.

thanks and best wishes

abdul n. khan

---
class CCurrency
{
// Constructors
public:
CCurrency();
CCurrency(CURRENCY cySrc);
CCurrency(const CCurrency& curSrc);
CCurrency(const _variant_t & varSrc);
CCurrency(long nUnits, long nFractionalUnits);
CCurrency(__int64 int64Value);
// Attributes
public:
enum CCurrencyStatus
{
valid = 0,
invalid = 1, // Invalid currency (overflow, div 0,
etc.)
null = 2, // Literally has no value
};
CURRENCY m_cur;
CCurrencyStatus m_status;
void SetStatus(CCurrencyStatus status);
CCurrencyStatus GetStatus() const;
// Operations
public:

const CCurrency& operator=(CURRENCY cySrc);
const CCurrency& operator=(const CCurrency& curSrc);
const CCurrency& operator=(const _variant_t & varSrc);

BOOL operator==(const CCurrency& cur) const;
BOOL operator!=(const CCurrency& cur) const;
BOOL operator<(const CCurrency& cur) const;
BOOL operator>(const CCurrency& cur) const;
BOOL operator<=(const CCurrency& cur) const;
BOOL operator>=(const CCurrency& cur) const;

// CCurrency math
CCurrency operator+(const CCurrency& cur) const;
CCurrency operator-(const CCurrency& cur) const;
const CCurrency& operator+=(const CCurrency& cur);
const CCurrency& operator-=(const CCurrency& cur);
CCurrency operator-() const;

CCurrency operator*(const CCurrency& cur) const;

CCurrency operator*(long nOperand) const;
CCurrency operator*(float nOperand) const;
CCurrency operator*(double nOperand) const;
CCurrency operator/(long nOperand) const;
CCurrency operator/(float nOperand) const;
CCurrency operator/(double nOperand) const;

const CCurrency& operator*=(long nOperand);
const CCurrency& operator/=(long nOperand);
const CCurrency& operator*=(float nOperand);
const CCurrency& operator/=(float nOperand);
const CCurrency& operator*=(double nOperand);
const CCurrency& operator/=(double nOperand);

operator CURRENCY() const;
operator _variant_t() const;

// CCurrency definition
void SetCurrency(long nUnits, long nFractionalUnits);
CCurrency Absolute();
};

CCurrency CCurrency::operator*(float nOperand) const
{
if (!GetStatus() == valid)
return *this;
CCurrency curOperand;
VarCyFromR4(nOperand,&curOperand.m_cur);
CCurrency curResult;
HRESULT hr = VarCyMul(*this, curOperand,&curResult.m_cur);
if FAILED(hr)
{
curResult.SetStatus(invalid);
curResult.m_cur.int64 = 0;
}
return curResult;

}

CCurrency CCurrency::operator*(double nOperand) const
{
if (!GetStatus() == valid)
return *this;
CCurrency curOperand;
VarCyFromR8(nOperand,&curOperand.m_cur);
CCurrency curResult;
HRESULT hr = VarCyMul(*this, curOperand,&curResult.m_cur);
if FAILED(hr)
{
curResult.SetStatus(invalid);
curResult.m_cur.int64 = 0;
}
return curResult;
}

Mar 6 '06 #5
ab**********@hotmail.com wrote:
Hello,
I am working on a program written by someone else and facing problems
in precisions due to usage of floating point date types. My input is
are the values in the rows of database (MS SQL Server) where fixed
point datatypes are used to store input as well as result e.g.
decimal(16,6) & money.

As the end I end up only using precision of 4 decimal instead of 6.
So far two people have responded and they both, independently told you
no to use floating point to represent currency. Dare I say, don't use
floating point to store currency?
Any help to make this program more robust for more real implementation.
Well, ignoring the responses you don't like won't solve it.
I have started to consider writign a class for fixed point arithmatic
datatype. Please let me know if it is a good start.


That's specifically what you have been told to do. At least twice.

Ben Pope
--
I'm not just a number. To many, I'm known as a string...
Mar 6 '06 #6
Hello ben
Which data type should I use to store decimal(16,6)?

Mar 6 '06 #7
Hello ben
Which data type should I use to store decimal(16,6)?

Mar 6 '06 #8
1) database datatype "money" is being handled by class CCurrency, which
uses structure CURRENCY that is defined by
typedef struct tagCY
{
unsigned long Lo;
long Hi;
} CURRENCY;
Members
Lo : Low-order 32 bits of the currency value.
Hi : High-order 32 bits of the currency value.
Remarks : The CURRENCY structure is a scaled integer representation of
a decimal number with four digits to the right of the decimal point. A
stored value of 327500, for example, is to be construed as representing
a currency value of 32.7500.

Therefore in my understanding "database datatype money" is being
handled by fixed point datatype instead of floating point. Please
correct me if I am wrong here.

The only problem is handling of "database datatype decimal(16,6)". I
know that I (or someone who originally wrote the program) shouldn't
have used troubling floating point datatype (single precision / double
precision).

But what alternate solution should I be doing? In my understanding that
is a very typical and generic problem that is taken care by many
people. I will appreciate any help to some article or documentation or
example will be of great help.

Does C++ or MS Visual C++ support "decimal" datatype?

Mar 6 '06 #9

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

Similar topics

8
by: Jonathan Fielder | last post by:
Hi, I have a 32 bit integer value and I wish to find the single precision floating point value that is closest to but less than or equal to the integer. I also have a similar case where I need...
9
by: Sisyphus | last post by:
Hi, I have some software that does the following (in an attempt to determine whether the double x, can be represented just as accurately by a float): void test_it(double x) { float y = x;...
13
by: maadhuu | last post by:
hello , i would like to know as to why double is more efficient than float . thanking you, ranjan.
6
by: James Thurley | last post by:
According to the docs, floats are 32 bit and doubles are 64 bit. So using floats should be faster than using doubles on a 32 bit processor, and my tests confirm this. However, most of the Math...
5
by: Kubik | last post by:
Hi! Let's see, we got: float var=4.6f; //as we know 414/4.6 shoud be equal to 90 but Math.Ceiling(414/var) gives us 91 but (414/var).ToString() prints '90'.
6
by: karthi | last post by:
hi, I need user defined function that converts string to float in c. since the library function atof and strtod occupies large space in my processor memory I can't use it in my code. regards,...
60
by: Erick-> | last post by:
hi all... I've readed some lines about the difference between float and double data types... but, in the real world, which is the best? when should we use float or double?? thanks Erick
116
by: Dilip | last post by:
Recently in our code, I ran into a situation where were stuffing a float inside a double. The precision was extended automatically because of that. To make a long story short, this caused...
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...
3
by: Arnie | last post by:
Folks, We ran into a pretty significant performance penalty when casting floats. We've identified a code workaround that we wanted to pass along but also was wondering if others had experience...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
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,...
0
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...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.