Hi,
Our client encountered the problem of getting a Json array in which one element has a value in exponential form.
@Call to Progress.Json.ObjectModel.JsonObject:GetDecimal( ) failed. Cannot transform JSON number value to ABL decimal value, JSON value has an exponent. (16061)
We get this value in the code like this:
disk_share.face_value = (IF oTmpIt:Has("face_value") THEN oTmpIt:GetDecimal("face_value") ELSE 0)
Example of value:
"face_value": 6.25e-6,
We haven't found other than this:
IF oTmpIt:Has("face_value")
THEN DO:
ASSIGN cStr = oTmpIt:GetJsonText("face_value").
IF INDEX(cStr, "e") > 0
THEN DO:
ASSIGN base = DECIMAL(SUBSTRING(cStr, 1, INDEX(cStr, "e") - 1))
power = INTEGER(SUBSTRING(cStr, INDEX(cStr, "e") + 1 ))
disk_bond.face_value = base * EXP(10, power).
END.
ELSE ASSIGN disk_bond.face_value = oTmpIt:GetDecimal("face_value").
END.
This seems to work, but maybe in ABL (4GL) there is another more efficient way to do this with the built-in ABL functions?
Regards,
Valeriy
Please vote for this extension:
In PTS says that there no built-in functionality available in ABL to convert exponential notation to decimal value, and offered to submit an idea for a Progress product enhancement.
|
It is OE 11.7.2 on Windows.
update: 11.7.1
Thank you, Mike,
I'll do that.
In PTS says that there no built-in functionality available in ABL to convert exponential notation to decimal value, and offered to submit an idea for a Progress product enhancement.
Please vote for this extension:
I think that this should be a bug regardless.
We should handle exponent-numbers but if we won't then we should at lest let you figure out it's an exponential number and be able to deal with it cleanly, without explicitly trapping for the 16061 error.
I'm adding an "obvious manual workaround", just in case someone finds this thread and is hoping for a temp solution - get the value from the JSON as a character and parse it with .Net.
vDecimalValue = System.Decimal:Parse (<character value>, System.Globalization.NumberStyles:Any).
Sadly that will only work on Windows.
I've added a version of Valeriy's code into the OpenEdge.Core.Util.MathUtil class that will be in the next releases. The code is below FYI.
/* Keep the default in a readonly property - it is 10 */ define static private property DEFAULT_BASE as integer initial 10 no-undo get. /** Converts an exponent (123e4) value into a decimal using a exponent base of 10. @param character The exponent value @param decimal The converted value */ method static public decimal ExponentialToDec(input pExpVal as character): return MathUtil:ExponentialToDec(pExpVal, DEFAULT_BASE). end method. /** Converts an exponent (123e4) value into a decimal. The format is nnn[.nnn]e[-]nnn <base>e<exponent> The <exponent> is raised as a power of the exponent-base. @param character The exponent value @param integer The exponent base. Must be a positive value (>0) @param decimal The converted value */ method static public decimal ExponentialToDec(input pExpVal as character, input pBase as integer): define variable idx as integer no-undo. define variable decVal as decimal no-undo initial 0.00. define variable coefficient as decimal no-undo. define variable exponent as integer no-undo. if String:IsNullOrEmpty(pExpVal) then return decVal. Assert:IsPositive(pBase, 'Exponent base'). assign idx = index(pExpVal, 'e':u). if idx eq 0 then assign decVal = decimal(pExpVal). else assign coefficient = decimal(substring(pExpVal, 1, idx - 1)) exponent = integer(substring(pExpVal, idx + 1)) decVal = coefficient * exp(pBase, exponent) . return decVal. end method.