Int and Fix problem (1 Viewer)

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
I have the strangest problem....

I have this application that creates an export intended for an erp system. This systems expects a decimal point (not a comma) and becuase we have international coworkers who have different regional settings I cannot rely on that beeing correct. So i created this function:
Code:
Function MakeAmount(Amount As Double) As String
    Dim x As String
    x = Fix(Amount * 100) ' also tried using Int
    If Len(x) = 1 Then x = "00" & x
    If Len(x) = 2 Then x = "0" & x
    MakeAmount = Left(x, Len(x) - 2) & "." & Right(x, 2)
End Function
Thinking, this will allways put a point where needed. However for some reason it sometimes takes away one cent.
If I put in 8.17 it strangely returns 8.16
?makeamount(8.17)
8.16
I need to be able to handle any number ranging from 0.01 to 999999999.99

Has any one ever experienced anything alike? What is the solution?
I am stuck... I need a decimal point allways independant of regional settings, how can i do that?

Regards

p.s. No, Format does not work .... :(
 
Last edited:

Travis

Registered User.
Local time
Yesterday, 17:00
Joined
Dec 17, 1999
Messages
1,332
I ran tests and it seems that the fix line is using some mathimatical presidence.

You can fix this issue by changing your code as follows:
This will force the Amount * 100 calc prior to the Fix
Code:
Function MakeAmount(Amount As Double) As String
    Dim x As String
    x = (Amount * 100)
    x = Fix(x)
    If Len(x) = 1 Then x = "00" & x
    If Len(x) = 2 Then x = "0" & x
    MakeAmount = Left(x, Len(x) - 2) & "." & Right(x, 2)
End Function
 

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
This is very strange .... very strange indeed ....

I did not think of testing that ... and now i find the "fix" i thought up has a problem with it as well :(

I tested it with all numbers from 0.01 to 10.00 and it indeed all seems OK now.

Thanks for your "fresh look" at things.

Regards
 

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
:eek: NOOOOOOOOOO

Yes, I am loosing cents again... Even with the new thing....

583.31 will become 583.30 ... AAARGH why is this not as simple as it looks.... ????

Greetz
 

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
I have now changed it to use round *sigh* I hate my Job !

Code:
Function MakeAmoun(Amount As Double) As String
    Dim x As String, y As Double
    y = Amount * 100
    x = Round(y, 0) ' doing Int(amount*100) generates problems where 8.17 sometimes is "rounded" down to 8.16
    
    If Len(x) = 1 Then x = "00" & x
    If Len(x) = 2 Then x = "0" & x
    MakeAmount = Left(x, Len(x) - 2) & "." & Right(x, 2)
    
End Function

Why are doubles input as 583.56 beeing "mutilated" to 583.559999999999 ???

AAARGH why do i not understand?

Anyone have any thoughts?
 

RoyVidar

Registered User.
Local time
Today, 02:00
Joined
Sep 25, 2000
Messages
805
Singles and doubles store the closest approximation of the number not being exactly that number;) So, it doesn't really store 1 if you wan't to store 1, but 1.000000000000001 or 0.9999999999999999 or something along those lines.

Would the Currency datatype perhaps fit better to your situation.
 

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
Changing the datatype would make me go thru the application and have to change double to currency in a lot of places :(

It is something to baer in mind when developping a new one. Does Currency not have this problem?
Up to how many decimals can a currency hold? => RTH !

Greetz
 

RoyVidar

Registered User.
Local time
Today, 02:00
Joined
Sep 25, 2000
Messages
805
Not up to date on abbreviations, what is RTH?

While in design view of a table, place the cursor in the datatype part and hit F1 (now that one, I know, that's RTM;)).

"Currency values and numeric data used in mathematical calculations involving data with one to four decimal places. Accurate to 15 digits on the left side of the decimal separator and to 4 digits on the right side"

and later

"Tip Use the Currency data type for a field requiring many calculations involving data with one to four decimal places Single and Double data type fields require floating-point calculations. The Currency data type uses a faster fixed-point calculation."

(typos are mine;))

Do a search with the terms currency accuracy, there are some threads around.
 

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
H as in Help (or hit F1 or RTM or RTFM)

Why then does the currency not actually store 318.1799 where a double or single will store 318.179999999999 if you put 318.18 in ?

Round or format will "do the trick" but.... there are a lot of traps one can get into.... :(

I feel like an ass when i get into one of these pits that have been dug here and there ...

Regards
 

RoyVidar

Registered User.
Local time
Today, 02:00
Joined
Sep 25, 2000
Messages
805
As I understand, it will store max four digits.

Yes there are traps. When converting, what to do when the actual value in a single or double field have lot's of decimals and you wish only two... If you don't handle the conversion "manually" or semi automatic through code, Access will probably do some rounding.

I have no good answer, but will probably exprerience some fun with those issues when converting some old thingies to SQL server, at the same time do some structural changes.

Whatever you decide to do - test, test, test and test in backups...

A friend ones said, Real Men don't backup, but often cry...

This - and calculating date/time has never been among my strong sides;)
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Yesterday, 19:00
Joined
Feb 28, 2001
Messages
27,193
Let's clear some air. First, as to storage limitations

A DOUBLE stores 64 bits subdivided so that it holds approximately 15 decimal digits and an explicit exponent good to about 10^(+/- 38 - roughly). The decimal point can "float" - which is why it is sometimes called FLOATING POINT instead of REAL. When you store a number containing a fraction, remember that it is a BINARY fraction but we live in a DECIMAL world. Sadly, that decimal world DOES NOT COME OUT EVEN in binary.

Food for thought... perverse beings that we are, if we all were quadradactylic instead of pentadactylic (four-fingered instead of five...), would we have settled on DECIMAL computers as our de facto standard? :rolleyes:

In Access, a DOUBLE is a "native" format for the computer. Fractional numbers that are powers of 2 always come out even on a computer. Numbers that involve denominators with any factors involving decimal numbers 3, 5, or 7 (primes less than 10 OTHER THAN 2) do not - in binary. Since 10 is 2*5, fractions of 10 don't come out even, either. If I recall correctly, 0.1 (decimal) is a repeating fraction in binary. Something like 0.00011001100110011 ...

So your issue when rounding, fixing, or ... INT'ing, I guess... is that if you had an approximation on your hands, you need to take into account that the number might NEVER be exact - particularly if you are truncating a decimal fraction on a non-decimal machine. This is where adding in a fudge factor might be a real strategy. Like, when computing balances to 0.01, explicitly add or subtract 0.005 before you truncate it. This does, of course, involve lots of math and scaling functions.

The same is not true for Currency. That is a special case because it is what some programming purists call a "cast" - I.e. you cast properties onto it that the underlying storage method really doesn't have. In this case, the cast is to be scaled by 4 decimal places. But it is REALLY a double-long integer. Some systems call this an OCTAWORD. Call it 16 bytes. 128 bits. One bit is the sign leaving 127 bits for the value. The limit on a CURRENCY value is, in essence, numbers ranging +/- (2^7) * (2^120) - then divided by 10,000 (scaled). Now, 2^10 ~ 10^3, so 2^120 ~ 10^36 (before scaling). That comes out to roughly 128 * (10^32) as a first approximation.

In American currency, that means you can count amounts to a tenth of a mil (rare monetary term indeed, since it never bought much in the first place and buys even less now...) for whole dollars up to 128 * (10^32). I don't know the American name for that quantity other than that next year's government spending will probably top that number. :mad:

(Supplement: The American version of that number would be named 12.8 DECILLION if I counted it right....)

Since this is a scaled INTEGER, it is always exact to 0.0001 currency units, whether we are talking Euros, Yen, or U.S. Dollars. To use it for simple transactions, just input the correct number including the right number of decimals. BUT remember that if computing tax or interest, you have a couple of digits you cannot usually see acting as guard digits to the right of the last digit you CAN see. And there is where "math artifacts" can creep in. To represent a fraction to fewer digits than are present in the scaled number, you have exactly the same problem with the first number you DIDN'T keep as you would have had with a DOUBLE. So if you choose to convert to CURRENCY from DOUBLE, you won't automagically get rid of all of your problems. You'll just change them to something else.

In the final analysis, you must recognize that any representation has its limits and take into account ways to help the computer find your answer. Each path has its problems and I cannot advise you which way to go. I'll offer this thought... CURRENCY can stay "exact" for whole numbers longer than DOUBLE can... but if your application deals with a 15-digit amount of money, you're doing well anyway.
 

namliam

The Mailman - AWF VIP
Local time
Today, 02:00
Joined
Aug 11, 2003
Messages
11,695
RoyVidar said:
As I understand, it will store max four digits.
Whatever you decide to do - test, test, test and test in backups...

A friend ones said, Real Men don't backup, but often cry...

This - and calculating date/time has never been among my strong sides;)
test? What is test? I have heard that word somewhere before....
I cannot even remember the last time i was allowed to do proper testing on one of my "products" I do backup, and often. Use version nrs as wel to keep track of everything.

I still find it a pain, if i put something in i want that out. But appearently thats not the way it goes. Maybe i should store these things in Text format instead of number format :)

Greetz
 

Users who are viewing this thread

Top Bottom