Issue 31001 - Currency variables do not properly assign to some values. Even CCur has problems.
Summary: Currency variables do not properly assign to some values. Even CCur has probl...
Status: ACCEPTED
Alias: None
Product: App Dev
Classification: Unclassified
Component: api (show other issues)
Version: 3.3.0 or older (OOo)
Hardware: All All
: P3 Trivial
Target Milestone: ---
Assignee: AOO issues mailing list
QA Contact:
URL:
Keywords: oooqa
Depends on:
Blocks:
 
Reported: 2004-07-01 23:18 UTC by andrew
Modified: 2017-05-20 11:27 UTC (History)
4 users (show)

See Also:
Issue Type: DEFECT
Latest Confirmation in: ---
Developer Difficulty: ---


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description andrew 2004-07-01 23:18:35 UTC
Problem:
[code]
Sub BadCurrency
   Dim c As Currency
   Dim d As Double
   d = 200.432
   c = d
   Print c             ' 200.4319
   Print CCur(d)       ' 200.4319
End Sub
[/code]

This should show 200.4320 when it is printed. I am certain that the problem is
because the value is converted to a double precision number before it is
converted to a currency value.
[code]
   Dim c As Currency
   c = 200.432
   Print c             ' 200.4319
[/code]
A currency variable acts like an integer. The currency type is a fixed precision
floating point number that uses four decimal digits of precision. The problem is
with the conversion from a double to the internal INT64. First, the constant is
converted to a Double, and then it is converted to the INT64.

The trouble starts with the file svtools/source/sbx/sbxconv.hxx
[code]inline
SbxINT64  ImpDoubleToCurrency( double d )
                  { return ImpDoubleToINT64( d * CURRENCY_FACTOR ); }
[/code]
The implementation of this routine, is as follows:
[code]
SbxINT64 ImpDoubleToINT64( double d )
{
  SbxINT64 nRes;
  nRes.Set( d );
  return nRes;
}
[/code]
Great, so now I know that it has to do with the Set method! See
svtools/inc/sbxvar.hxx
[code]
void Set(double n)
{
  if( n >= 0 )
  {
    nHigh = (INT32)(n / (double)4294967296.0);
    nLow  = (UINT32)(n - ((double)nHigh * (double)4294967296.0));
  }
  else {
    nHigh = (INT32)(-n / (double)4294967296.0);
    nLow  = (UINT32)(-n - ((double)nHigh * (double)4294967296.0));
    CHS();
  }
}
[/code]
Our number is small, so nHigh is set to zero. nLow is equivalent to (UINT32)(n).
I need to remind myself, because I have forgotten, exactly what the storage
method is, and how the cast works, but I suspect that this is a bit operation
more than anything, and it will simply take the appropriate bits.
Unfortunately, the number in question, is probably not represented exactly, so
if the bits are simply chopped off, then we lose the guard bits that would have
allowed a double precision number to have appeared as though things were working
nicely.
I suppose that this is enough for now!

Andrew Pitonyak
Comment 1 andrew 2004-07-01 23:20:14 UTC
You can see a pretty version of this error at the following location:
http://www.oooforum.org/forum/viewtopic.php?p=38913#38913
Comment 2 stephan.wunderlich 2004-07-06 14:24:08 UTC
SW->AB: Basic-runtime, looks like one for you
Comment 3 christianjunker 2005-08-07 20:41:30 UTC
still happens for 2.0 .
Comment 4 ab 2006-02-16 06:51:23 UTC
Started
Comment 5 ab 2006-03-07 13:48:19 UTC
ab: According to discussion with sw/kso -> 2.0.3
Comment 6 ab 2006-04-28 12:24:34 UTC
-> 2.0.4
Comment 7 ab 2006-04-28 12:25:07 UTC
Really -> 2.0.4 :-)
Comment 8 ab 2006-07-18 09:09:22 UTC
-> 2.x due to code freeze and limited resources
Comment 9 ab 2006-08-21 14:09:03 UTC
-> 2.1
Comment 10 ab 2006-10-16 16:34:36 UTC
According to discussion with mba/kso -> 2.2 as cws ab30
has to be integrated very soon.
Comment 11 ab 2007-01-02 14:15:32 UTC
2.x due to limited resources.
Has to be evaluated and targeted together with all other 2.x tasks.
Comment 12 ab 2007-11-16 13:25:51 UTC
3.x due to limited resources
Comment 13 squenson 2008-07-16 20:53:31 UTC
As published in the OOo User forum by lorenzo2
(http://user.services.openoffice.org/en/forum/viewtopic.php?f=45&t=7885&p=37054), the
currency type is not properly handled in some basic math operations. There is an
overflow after (2^31 - 1) / 10000.

How to reproduce the bug
------------------------

1. Create the following macro in an empty Calc document

Sub Main

   Dim oSheet as object, oCell as object
   Dim cost as currency, total as currency
   Dim buy as integer
   
   oSheet=ThisComponent.Sheets.getByName("Sheet1")
   
   oCell=oSheet.getCellByPosition(0,0) 'A1 
   buy = oCell.getValue               
   
   oCell=oSheet.getCellByPosition(1,0) 'B1
   cost = oCell.getValue
     
   total = buy*cost
   oCell=oSheet.getCellByPosition(2,0) 'C1
   oCell.setValue(total)

End Sub

2. Now, if you set A1 to 5 and B1 to 40000 and execute the macro, cell C1
contains 200000, as expected.

3. If you now change B1 to 50000 and execute the macro again, C1 doesn't contain
the expected value of 250000 - on my computer, it's now 38,252,449,584,978.1
Comment 14 bmarcelly 2008-08-05 11:00:50 UTC
Here is a more obvious example based on squenson comment.

Dim A As Currency, B As Currency, R As Currency
A = 4
B = 50000
R = A*B
print "R=" & R ' result OK : 200000.0000
A = 5
R = A*B
print "R=" & R ' Result example : 60686005228817.4336

The last result is variable, just like a random number generator. You have also wrong 
results with A = 4.3 for example. Tested on version 2.4.1.
It's a pity that resolution of this report is systematically delayed.
Comment 15 Marcus 2017-05-20 11:27:43 UTC
Reset assigne to the default "issues@openoffice.apache.org".