Comments (8)
This bug like this
There is my customization to fix
public class SumPrecision implements Function {
@Override
public String getName() {
return "psum";
}
@Override
public int getMinArguments() {
return 1;
}
@Override
public int getMaxArguments() {
return 1;
}
@Override
public JsonNode call(JsonNode input, JsonNode[] arguments) {
JsonNode array = arguments[0];
if (array.isNull()) {
return NullNode.instance;
} else if (!array.isArray()) {
throw new JsltException("psum(): argument must be array, was " + array);
}
BigDecimal sum = new BigDecimal("0.0");
boolean integral = true;
for (int ix = 0; ix < array.size(); ix++) {
JsonNode value = array.get(ix);
if (!value.isNumber()) {
throw new JsltException("psum(): array must contain numbers, found " + value);
}
integral &= value.isIntegralNumber();
sum = sum.add(value.decimalValue());
}
if (integral) {
return new LongNode(sum.longValue());
} else {
return new DecimalNode(sum);
}
}
}
from jslt.
Not sure I understand what the bug is. Can you give an example with JSON input + JSLT code and wrong output?
from jslt.
This is JSON input
[
{
"taskSeqno": "100000265920",
"taskSeqnoFk": "100000396209",
"ramiCode": "11",
"ramiCodeDesc": "22",
"tranStatus": "05",
"tranStatusDesc": "已放款",
"tranDate": "20230101",
"actualAmount": "23000.123",
"actualAmount2": 23000.123,
"lastOperation": "已放款",
"lastOperationCode": "05",
"refundFlag": "N",
"totalReturnAmount": "0",
"refundDate": "20221102",
"tranDesc": "点错了",
"returnTranDesc": "无效果",
"returnAmount": 4000,
"retractStatus": "00",
"retper": "01",
"totTranAmount": 1000.55,
"tranAmount": 1050,
"downPayAmount": 1122.33,
"paymentDProp": 18,
"loanTerm": 12,
"ramiLafratvl": 3.11,
"lafratvl": 1.22,
"discountRate": 5.44,
"factoryRate": 6.55,
"agencyRate": 7.88,
"agencyGroupRate": 8.77,
"ramiCmsn": 4455.66,
"cstCmsn": 3355.55,
"mchtCmsn": 4433.22,
"finalPayment": 7777.55,
"paymentFProp": 45.88,
"isFlexRepymt": "1",
"sxfstage": "1",
"discountFlg": "0",
"discountId": "001"
},
{
"taskSeqno": "100000265920",
"taskSeqnoFk": "100000396209",
"ramiCode": "11",
"ramiCodeDesc": "22",
"tranStatus": "05",
"tranStatusDesc": "已放款",
"tranDate": "20230104",
"actualAmount": "23000",
"actualAmount2": 23000.123,
"lastOperation": "已放款",
"lastOperationCode": "05",
"refundFlag": "N",
"totalReturnAmount": "0",
"refundDate": "20221102",
"tranDesc": "点错了",
"returnTranDesc": "无效果",
"returnAmount": 4000,
"retractStatus": "00",
"retper": "01",
"totTranAmount": 1000.55,
"tranAmount": 1050,
"downPayAmount": 1122.33,
"paymentDProp": 18,
"loanTerm": 12,
"ramiLafratvl": 3.11,
"lafratvl": 1.22,
"discountRate": 5.44,
"factoryRate": 6.55,
"agencyRate": 7.88,
"agencyGroupRate": 8.77,
"ramiCmsn": 4455.66,
"cstCmsn": 3355.55,
"mchtCmsn": 4433.22,
"finalPayment": 7777.55,
"paymentFProp": 45.88,
"isFlexRepymt": "1",
"sxfstage": "1",
"discountFlg": "0",
"discountId": "001"
},
{
"taskSeqno": "100000265920",
"taskSeqnoFk": "100000396209",
"ramiCode": "11",
"ramiCodeDesc": "22",
"tranStatus": "05",
"tranStatusDesc": "已放款",
"tranDate": "20230108",
"actualAmount": "23000",
"actualAmount2": 23000.123,
"lastOperation": "已放款",
"lastOperationCode": "05",
"refundFlag": "N",
"totalReturnAmount": "0",
"refundDate": "20221102",
"tranDesc": "点错了",
"returnTranDesc": "无效果",
"returnAmount": 4000,
"retractStatus": "00",
"retper": "01",
"totTranAmount": 1000.55,
"tranAmount": 1050,
"downPayAmount": 1122.33,
"paymentDProp": 18,
"loanTerm": 12,
"ramiLafratvl": 3.11,
"lafratvl": 1.22,
"discountRate": 5.44,
"factoryRate": 6.55,
"agencyRate": 7.88,
"agencyGroupRate": 8.77,
"ramiCmsn": 4455.66,
"cstCmsn": 3355.55,
"mchtCmsn": 4433.22,
"finalPayment": 7777.55,
"paymentFProp": 45.88,
"isFlexRepymt": "1",
"sxfstage": "1",
"discountFlg": "0",
"discountId": "001"
}
]
This is JSON result
{
"tranDate" : "20230108",
"customerRate" : 1.22,
"discountAmount" : 6877.5,
"firstPaymentRatio" : 18,
"finalPaymentRatio" : 45.88,
"finalPayment" : 7777.55,
"actualAmount" : 69000.12299999999,
"actualAmount2" : 69000.369,
"loanTerm" : 12,
"totTranAmount" : 1000.55,
"totalRate" : 1000.55,
"totalHandlingFee" : 4455.66
}
Such as JSLT script
{
"tranDate" : .[size(.) - 1].tranDate,
"customerRate" : .[0].lafratvl,
"discountAmount" : (.[0].tranAmount * .[0].factoryRate),
"firstPaymentRatio" : .[0].paymentDProp,
"finalPaymentRatio" : .[0].paymentFProp,
"finalPayment" : .[0].finalPayment,
"actualAmount": sum([for(.)
number(.actualAmount)]),
"actualAmount2": sum([for(.)
number(.actualAmount2)]),
"loanTerm" : .[0].loanTerm,
"totTranAmount" : .[0].totTranAmount,
"totalRate" : .[0].totTranAmount,
"totalHandlingFee" : .[0].ramiCmsn
}
Look at
"actualAmount"
from jslt.
Okay, so your complaint is that
sum([ 23000.123, 23000, 23000 ])
produces 69000.12299999999
instead of 69000.123
. Which is how decimal numbers work.
If I try this with Python I get:
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 19 2020, 20:48:48)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> sum([ 23000.123, 23000, 23000 ])
69000.12299999999
If I do it in JavaScript I get:
Welcome to Node.js v19.3.0.
Type ".help" for more information.
> 23000.123 + 23000 + 23000
69000.12299999999
Your proposed solution is to use BigDecimal instead. That will be slower and more memory-intensive, but perhaps it's worth it. People have asked for the same thing before (issue #68).
What I wonder is: why do people consider this a problem? Is it because you're just not comfortable with floating numbers behaving they way they do, or is it because there is a real, practical problem involved?
from jslt.
Think for u solution,This kind of scenario happens in which us want to process the amount field using JSLT script。
Script calculations will be used in API transfer,lowcode System entity transformations(only based on Spring or EJB).
from jslt.
I wanted to understand what this would look like if the JSON were loaded into a Java process, so I wrote this small program:
public class Test {
public static void main(String[] argv) {
System.out.println("float: " + Float.parseFloat("69000.123"));
System.out.println("double: " + Double.parseDouble("69000.123"));
}
}
The output is:
float: 69000.125
double: 69000.123
If I add a few more zeroes the float loses the digits after the decimal completely, but the double keeps working.
from jslt.
The problem is not limited to the sum() function, because 23000.123 + 23000 + 23000
produces 69000.12299999999
.
from jslt.
You could change the JSTL to do this:
{
"actualAmount": round (1000 * sum ([ for (.) number (.actualAmount) ] )) / 1000
}
It would still have rounding error.
A slow alternative would be
def calculateActualAmount (amounts)
let int = floor ($amounts / 1000)
let fraction = $amounts - (1000 * $int)
let result = join ([ string (floor ($fraction / 100)), string (floor (mod ($fraction, 100) / 10)), string (mod ($fraction, 10)) ], "")
join ([ $int, $result], ".")
{
"actualAmount": calculateActualAmount (sum ([ for (.) floor (1000 * number (.actualAmount)) ] ))
}
Ugly, I admit.
from jslt.
Related Issues (20)
- Built-in sha256-hex function is not thread-safe HOT 6
- Unable to retrieve the values of the nested loops using JSLT HOT 1
- Pipe Operator not affecting Context HOT 3
- Complex Nesting For loop issues HOT 3
- Support for processing nested JSON
- Determine index of current item in object array HOT 3
- JsltJsonFilter clarification
- Variables, Scope and Import HOT 10
- Pass values from parent to imported jslt HOT 3
- I want to call external java method in jslt during transformation, is it possible??? HOT 3
- How to set counter value after each iteration of for loop in jslt HOT 6
- How to compare two arrays and get unique value HOT 4
- Is it possible to retrieve the common values from two arrays?i.e the values which are available in both the arrays HOT 2
- How to push elements to an array HOT 6
- How to round off value to 2 digit precision. Eg 55.0000 to 55.00 HOT 11
- Can enhance matcher expression to operate on a target specified with dot expression? HOT 2
- Need help with transforming by adding root fields to child array elements HOT 1
- json key have space HOT 1
- Filter out all keys with a specific name from all objects HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jslt.