Tag: decimals

Decimal points and functions

This is one of those issues that arise from me coming from a different background than what I imagine a typical Lansa developer, indeed a typical i series developer, come from. It is a useful reminder what decimals actually mean.

For example, I have a repository field that is defined like this:

Define Field(#JSN) Type(*SIGNED) Length(4) Decimals(2)

That means, a signed decimal value with 2 digits before the decimal point and 2 digits after the decimal point. In a function, I calculate the value and exchange it back to application calling. In that application, I (unfortunately) have an override, changing the number of decimals.

Override Field(#JSN) Decimals(1)

This was probably done to format the display of the value but where I imagined the value would be passed in a lower level format and then parsed in relation to the definition, this is not what happens.

Instead, the value is still the same 4 digits, but one of those that was after the decimal point is now before the decimal point. The value has been multiplied by 10^1; a value of 0.21 is now 2.1.

Because the override only moved the decimal point.

ROUND_UP – no, I don’t think so

The documentation for CHANGE’s ROUND_UP parameter states, among other things, that

If the intermediate work fields involved do not have at least one more decimal position than the field nominated in the FIELD parameter, then the ROUND_UP parameter will be ignored and treated as if ROUND_UP(*NO) was specified.

I have difficulty finding documentation on how intermediate work fields are created, if no PRECISION parameter is given, but there are a few implied hints in the documentation for PRECISION.

So, in my concrete example, I have one 9,0 number divided by a 10,0 number. The documentation implies the intermediate work fields will be 10,0. My result field is a 3,0 number.

The actual numbers are 122,682,586 and 1,000,000, respectively. I really would like to get 123 as the result in this particular case.

Just doing a

Change Field(#RESULT) To('#BIG / #SMALL')

gives me 122. Doing

Change Field(#RESULT) To('#BIG / #SMALL') Round_Up(*YES)

gives me 123. Great, but not something that ought to have worked. Doing the right thing,

Change Field(#RESULT) To('#BIG / #SMALL') Precision(11 1) Round_Up(*YES)

also gives me 123. And, though the parameter is called ROUND_UP, it actually does the “half adjust” which I found a description of that seems like it would do the right thing.


Note: Embarrassingly, I was under the impression that the length of a numeric field was the number of digits before the decimal. It was just recently I found out it was the length including the decimals.

Overflow

One thing that surprised me, and made me waste a day, was that there is no check for overflow in numeric operations by default.

If I try to divide by zero, my program crashes and I even get a very precise explanation of why, but overflowing provides neither.

So, a field defined as Packed(2,0) with

Define Field(*HMJPCK2) Type(*PACKED) Length(2) Decimals(0) Default(0)

it can only hold values between -99 and 99, inclusive. That is not the surprise, the surprise comes from the missing error when going beyond these values. 99 + 10 will give me 9 and no error.

I am very tempted to write a function to handle simple arithmetics to give me the proper error messages but I am too new at this language to start doing that.

Assumptions when dealing with decimals and thousand separators

I have enjoyed the lists of typical, and erroneous, assumptions we developers make with regards to dates and time, geography, names, addresses and genders. So I will here add a short list of erroneous assumptions commonly made about decimals and separators:

  1. The decimal point and the separator is globally the same.
    The wikipedia page for the decimal mark lists at least 11 different characters and combinations.
  2. The decimal point is a dot and the thousand separator is a comma.
    This is the default in programming, thanks to most development principles having originated in USA. But, alas, in most European countries it is exactly the opposite.
  3. At least, they are the same for every country.
    Except when they are not. Canada uses different rules depending on language.
  4. What about for all situations within the same language?
    No, sorry. The Swiss use one rule currency and what is practically the exact opposite for other numbers.
  5. I got it now. At least they are always found in the ASCII character set.
    Of course not, not even close. The Japanese prefer characters found in their own character set. Eastern Arabic numerals likewise.
  6. OK, then I can assume that thousand separators are for every 3 digits, right?
    Not even close. If the Chinese or Japanese group their digits they prefer 4 digits.
  7. The rules for printed and handwritten numbers be the same?
    Sorry, some countries have different traditions depending on form. Spain, Italy, Switzerland and others are the special cases here.
  8. If there is a rule for separators for every X digits, they always apply. Definitely.
    Well, even the Americans seem to get this one wrong, as 4 digit numbers are often written without a thousand separator, but 5-or-more digit numbers with. This is however nothing compared to the Indians who find it natural to but a separator with before the final 3 digits, but for every 2 digits before that.
  9. The separators are the same for all positions within a single number.
    Yes. Except of course if the Japanese or Chinese choose to use thousand, or rather, myriad, separators, which depend on position.

See Wikipedia:Decimal_mark, Wikipedia:Japanese_numerals, Wikipedia:Eastern_Arabic_NumeralsHow the world separates its digits and How the world separates its decimals.