on 2024 Oct 24 4:03 PM
I am making a custom CDS View in S/4 HANA onPremise edition, where I want devide 2 fields and multiply result with another field. Fields are of custom dictionary type, which refers to a domain of currency type. Meaning these fields are 23 of length with 2 decimals.
Consider a CDS view column definition like this:
( a / b * c ) as d //my_calculated_column.
firstly, when using / operator, the operators needs to be casted to float.
So I use this:
( ( cast( a as abap.float) / cast( b as abap.float ) ) * cast( c as abap.float ) ) as d.
the problem is, that casting to float changes the decimals to be incorrect.
for example if column a has value 3497,97 after casting to float it becomes all the sudden to 3497,96999999... and same with other operators
Same can be achieved with constants eg:
cast( 3497.97 as abap.fltp) as fixed_of_f returns 3497,96999999.
causing the calculated result to be wrong compared to operators with real 2 decimal values.
For example:
If a = 3497,97 and b= 3497,97 and c=524,70 the result d via castings is 524,69 when it should be 524,70, because 3497,97 / 3497,97 = 1.
Casting the result to decimal is not possible, because fltp cannot be casted to any format.
I tried using function fltp_to_dec, which is not working when using casted result as parameter because it expects only a column. To avoid this, I created another CDS view, that uses this first CDS view as source and in second CDS view I used fltp_to_dec to convert my calculation result field to 2 decimal value, but it does not round it but just cuts to decimal leading the results being still wrong (eg 524,69 with above a, b, c values)
this is how second CDS view fields would be defined:
define view <second view name> as select from <first CDS view>
{
...
fltp_to_dec( c as abap.dec(23,2)) as c_dec
fltp_do_dec(d as abap.dec(23,2)) as d_dec.
Besides as wanted to use this CDS view in SE16 (yes, SAPGUI based), SE16 did not allowed to view fields of float type at all, so converting float fields to DEC was mandatory.
Also, using the Round function to round the calculated result to 2 decimals is not applicable either. That is because Round function does not accept input of type float.
A kind of mitigation is this:
Using DIVISION function instead of '/' . It would work for division at least, but when adding the '*' (multiply) operator, like this:
( DIVISION(a , b, 2) * c ) as d
ADT gives an error message 'Maximum accuracy 37 at DEC exceeded by an arithmetic expression' and that is because operator c being a currency with length 23 ( I tried with fixed value 0.15 and then it worked).
casting the operator c also to decimal(10,2) then works:
( DIVISION(a , b, 2) * casting( c as abap.dec(10,2) ) as d
With this solution I no longer need second CDS view that used ftlp_to_dec function.
So in the first place, why is casting to float changes the decimals? I am just thinking this could happen in any applications, even standard CDS views, that does casting to float in order to perform division calculation with '/' operator. Why would anyone use cast ( <column> as abap.float) if decimals are not kept intact?
Request clarification before answering.
SOLUTION by the original poster: CAST CURR to DEC, then DEC to DECFLOAT, and you can then divide.
NOT A SOLUTION: In ABAP 7.58, CAST of CURR to DECFLOAT isn't possible (compile error message: "CAST operand_1 of type CURR to type DECFLOAT34 is not possible"):
CAST( operand_1 AS decfloat34 ) / CAST( operand_2 AS decfloat34 )
Concerning the packed types, only DEC and QUAN may be casted to DECFLOAT (16 or 34). https://help.sap.com/doc/abapdocu_754_index_htm/7.54/en-US/index.htm?file=abencds_f1_arithmetic_expr...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This compiles in ABAP 7.58:
@AbapCatalog.sqlViewName: 'ZZSRO_CAST_CURR'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Cast CURR to DECFLOAT34 (via DEC)'
define view zzsro_cast_curr_to_decfloat34
as select from sbook
{
( cast( cast( loccuram as abap.dec(15,2) ) as abap.decfloat34 )
/ cast( cast( forcuram as abap.dec(15,2) ) as abap.decfloat34 )) as CurrencyExchangeRate
}
Raymond, no I did not checked that before my posting, but did know they existed. When now checked those functions, I recon they'd not provide any help to actual issue that converting decimal values to float leads to decimals being wrong as the first helping person says.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
41 | |
15 | |
10 | |
9 | |
6 | |
5 | |
5 | |
5 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.