Rounding while comparing N variable with number. How to avoid? - abap

Hello to every one and HAPPY NEW YEAR.
I have the following problem: a char field contains an amount and I want to make the following check: if wfile-dmbtr < 0.00
The code I use:
data: lv_dmbtr(18) type n.
write wfile-dmbtr to lv_dmbtr.
replace first occurrence of '.' in lv_dmbtr with ''.
translate lv_dmbtr using ',.'.
if lv_dmbtr <= '0.00'.
The problem is for values between 0.01 to 0.49, and the program most probably round them to 0 and returns True.
The dmbtr amounts have the following mask: 12.235,99. Does anyone knows how to overcome this issue?
Thanks in advance.
Elias

Elias. Happy new year to you too.
Type N does not allow the use of decimals (even though you might be able to see it in the debugger if you force such value). That's the reason why the number is being rounded and the condition evaluation 'seems' to fail.
In addition, after you do the number conversion / formatting, you might be better off using a decimal type variable to do the condition evaluation (such as type of data element MAXBT).
Example:
DATA: lv_dmbtr(18) TYPE c, " Used to be type N instead of pure CHAR.
lv_aux TYPE maxbt.
WRITE '0,01' TO lv_dmbtr.
REPLACE FIRST OCCURRENCE OF '.' IN lv_dmbtr WITH ''.
TRANSLATE lv_dmbtr USING ',.'.
CONDENSE lv_dmbtr.
lv_aux = lv_dmbtr.
IF lv_aux <= '0.00'.
BREAK-POINT.
ELSE.
BREAK-POINT. " It should enter this bracket for the value 0,01
ENDIF.
Hope it helps.

Related

DB2 showing 0 instead of decimal place

I am trying to calculate milliseconds into seconds for a field. I was using [field]/1000 and that works as long as the value is greater than 1. Once its under ``1 I get 0. So if the value is 460 I get 0 instead 0.46.
I tried the below:
RUNTIME/1000 as test,
CAST(RUNTIME/1000 as DECIMAL(5,2)) as test2
Refer to the Expressions article.
Two integer operands
If both operands of an arithmetic operator are integers, the operation
is performed in binary and the result is a large integer unless either
(or both) operand is a big integer, in which case the result is a big
integer. Any remainder of division is lost. The result of an integer
arithmetic operation (including negation by means of a unary minus
operator) must be within the range of the result type.

How do I calculate the sum efficiently?

Given an integer n such that (1<=n<=10^18)
We need to calculate f(1)+f(2)+f(3)+f(4)+....+f(n).
f(x) is given as :-
Say, x = 1112222333,
then f(x)=1002000300.
Whenever we see a contiguous subsequence of same numbers, we replace it with the first number and zeroes all behind it.
Formally, f(x) = Sum over all (first element of the contiguous subsequence * 10^i ), where i is the index of first element from left of a particular contiguous subsequence.
f(x)=1*10^9 + 2*10^6 + 3*10^2 = 1002000300.
In, x=1112222333,
Element at index '9':-1
and so on...
We follow zero based indexing :-)
For, x=1234.
Element at index-'0':-4,element at index -'1':3,element at index '2':-2,element at index 3:-1
How to calculate f(1)+f(2)+f(3)+....+f(n)?
I want to generate an algorithm which calculates this sum efficiently.
There is nothing to calculate.
Multiplying each position in the array od numbers will yeild thebsame number.
So all you want to do is end up with 0s on a repeated number
IE lets populate some static values in an array in psuedo code
$As[1]='0'
$As[2]='00'
$As[3]='000'
...etc
$As[18]='000000000000000000'```
these are the "results" of 10^index
Given a value n of `1234`
```1&000 + 2&00 +3 & 0 + 4```
Results in `1234`
So, if you are putting this on a chip, then probably your most efficient method is to do a bitwise XOR between each register and the next up the line as a single operation
Then you will have 0s in all the spots you care about, and just retrive the values in the registers with a 1
In code, I think it would be most efficient to do the following
```$n = arbitrary value 11223334
$x=$n*10
$zeros=($x-$n)/10```
Okay yeah we can just do bit shifting to get a value like 100200300400 etc.
To approach this problem, it could help to begin with one digit numbers and see what sum you get.
I mean like this:
Let's say, we define , then we have:
F(1)= 45 # =10*9/2 by Euler's sum formula
F(2)= F(1)*9 + F(1)*100 # F(1)*9 is the part that comes from the last digit
# because for each of the 10 possible digits in the
# first position, we have 9 digits in the last
# because both can't be equal and so one out of ten
# becomse zero. F(1)*100 comes from the leading digit
# which is multiplied by 100 (10 because we add the
# second digit and another factor of 10 because we
# get the digit ten times in that position)
If you now continue with this scheme, for k>=1 in general you get
F(k+1)= F(k)*100+10^(k-1)*45*9
The rest is probably straightforward.
Can you tell me, which Hackerrank task this is? I guess one of the Project Euler tasks right?

Why does round(143.23,-1) return 140?

For the query
SELECT round(143.23, -1)
FROM dual
I thought that the output will be 142 but the output i got is 140
can anyone help me by explaining this.
The second parameter indicates how many digits of precision after the decimal point you want to preserve. Thus, -1 means one digit before the decimal point. I.e., you're losing the "ones" digit and rounding to the nearest "tens", resulting in 140.
To get a whole number (143 in this case), you can pass 0 as the second parameter, or just omit it entirely, as that's the default.

Why is precision lost if resolving of the type left to the compiler?

What is the reason of the lost of precision if the decimal type of the variable is left to be defined by the compiler? Is this documented anywhere?
DATA: gv_1 TYPE p LENGTH 15 DECIMALS 2 VALUE '56555.31'.
DATA: gv_2 TYPE p LENGTH 15 DECIMALS 2 VALUE '56555.31'.
DATA: gv_3 TYPE p LENGTH 15 DECIMALS 2 VALUE '56555.34'.
DATA(gv_sum) = gv_1 + gv_2 + gv_3. "data type left to be resolved by the compiler
WRITE / gv_sum.
DATA: gv_sum_exp TYPE p LENGTH 15 DECIMALS 2. "explicit type declaration
gv_sum_exp = gv_1 + gv_2 + gv_3.
WRITE / gv_sum_exp.
The first sum results in
169666
The second one in
169665.96
As we know, the ABAP compiler brings all the operands of an arithmetic expression to the so-called calculation type. And we also know that data type with the largest value range determines the whole caclulation type. But you, probably, don't aware of some changes that were introduced to this process with the release of inline declarations in ABAP. Here they are:
If operands are specified as generically typed field symbols or formal
parameters and an inline declaration DATA(var) is used as the target
field of an assignment, the generic types contribute to the statically
detectable calculation type (used to determine the data type of the
declaration) as follows: ...csequence, clike, c, n, and p like p. If no type with a higher priority is involved, the type p with length 8 (no decimal places) is used for the declaration....
That is exactly what we see in debugger during execution of your code:

ceil() not working as I expected

I'm trying to divide one number by another and then immediately ceil() the result. These would normally be variables, but for simplicity let's stick with constants.
If I try any of the following, I get 3 when I want to get 4.
double num = ceil(25/8); // 3
float num = ceil(25/8); // 3
int num = ceil(25/8); // 3
I've read through a few threads on here (tried the nextafter() suggestion from this thread) as well as other sites and I don't understand what's going on. I've checked and my variables are the numbers I expect them to be and I've in fact tried the above, using constants, and am still getting unexpected results.
Thanks in advance for the help. I'm sure it's something simple that I'm missing but I'm at a loss at this point.
This is because you are doing integer arithmetic. The value is 3 before you are calling ceil, because 25 and 8 are both integers. 25/8 is calculated first using integer arithmetic, evaluating to 3.
Try:
double value = ceil(25.0/8);
This will ensure the compiler treats the constant 25.0 as a floating point number.
You can also use an explicit cast to achieve the same result:
double value = ceil(((double)25)/8);
This is because the expressions are evaluated before being passed as an argument to the ceil function. You need to cast one of them to a double first so the result will be a decimal that will be passed to ceil.
double num = ceil((double)25/8);