I am using VariantCopyInd . The source contains 1111.199999999. However after VariantCopyInd the value gets rounded off in the destination as 1111.200000. I would like to retain the original value . how can this be achieved ?
-
Post code that reproduces this problem. – Hans Passant Nov 30 '11 at 13:59
2 Answers
This has nothing to do with VariantCopyInd, but merely the fact that the literal as it exists in the code, has not exact representation in the floating point format used internally by COM Variants.
Therefore, there is no way to achieve what you want, except to use the CURRENCY type of variant. It will have limited precision, see MSDN:
CURRENCY types use a decimal representation internally, just like the code literal. You will still have to provide an indirect initialization (from string, not a float/double literal) in code, to prevent any unwanted representation effects.
A currency number stored as an 8-byte, two's complement integer, scaled by 10,000 to give a fixed-point number with 15 digits to the left of the decimal point and 4 digits to the right. This
IDispatch::GetTypeInforesentation
provides a range of 922337203685477.5807 to -922337203685477.5808.The
CURRENCY
data type is useful for calculations involving money, or for any fixed-point calculation where accuracy is particularly important.

- 374,641
- 47
- 450
- 633
-
@sameerkarjatkar: I understand. CComVariant is also just (a wrapper for) VARIANT. Updated my answer with my best hint: use currency (which uses decimal representation internally) – sehe Nov 30 '11 at 10:59
-
-
@sameerkarjatkar: By definition, a `VARIANT` is a discriminated union. If you store a `CURRENCY` value in a `VARIANT` no casting is involved. To use the value in _double_ arithmetics you could use `(double) dblVariant.cyVal.int64 / 10000.0`. No doubt, CComVariant has getters for this - but MSDN is at your disposal too – sehe Nov 30 '11 at 11:46
I found a very good link from msdn
enter link description here The link clearly indicates any number whose length is greater than 15 will evaluate into incorrect results .
Take 2 cases
1) 101126.199999999 will store a correct value , since the length is 15 . No conversion or precision loss 2) 111.12345678912345 will store incorrect value since the length is 17 . Conversion will be done

- 2,017
- 4
- 23
- 43
-
Unfortunately you missed the essential point: the page also mentions that `might not exactly approximate the decimal number` and `A value might not roundtrip if a floating-point number is involved`. This has _nothing_ to do with _decimal_ significant digits (in fact, the sample from the OP is less than 15 digits). – sehe Nov 30 '11 at 12:54
-
Oh. Also, the linked article doesn't even apply because it is **not** about .NET or even CLR. (You can expect the internal representation to be the same IEEE floating point standard, but that is not explicitely mentioned) – sehe Nov 30 '11 at 12:57
-
@sehe probably my question is not correct . Do you say that a floating point number of length 15 can also loose its precision or will get converted ? – sameer karjatkar Dec 01 '11 at 05:32
-
Precisely. This is somewhat of a [FAQ on SO](http://stackoverflow.com/questions/3748768/why-is-double0-6f-double6-10f). See wikipedia: [For instance, 1/5 cannot be represented exactly as a floating point number using a binary base but can be represented exactly using a decimal base](http://en.wikipedia.org/wiki/Floating_point#Overview) and ... – sehe Dec 01 '11 at 08:09
-
... [Any rational with a denominator that has a prime factor other than 2 will have an infinite binary expansion. This means that numbers which appear to be short and exact when written in decimal format may need to be approximated when converted to binary floating-point. For example, the decimal number 0.1 is not representable in binary floating-point of any finite precision; the exact binary representation would have a "1100" sequence continuing endlessly](http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding) – sehe Dec 01 '11 at 08:09
-
ok...I have a very simple scenario ,the user inputs a number like 101126.199999999 which I save into the database in Column whose datatype is NUMBER . I do not perform any arithmetic operations . This works good as long as the length is 15 , the moment i increase the length beyond 15 the value gets rounded off. I just want to be sure if this rounding off will occur only beyond length 15 – sameer karjatkar Dec 01 '11 at 08:28
-
The recipe is simple: either 1. provide storage sufficient precision and use decimal representations exclusively (look for: decimal, currency or money types) 2. provide _excess_ precision and round to the required precision. Note that in the latter case the [cumulative effects](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) of rounding errors can result in loss of precision – sehe Dec 01 '11 at 09:05