I have an application written in nodejs. The application needs to calculate a maritime levy. the calculation needs to match the result from the port. The levy calculator in the port is written in C#.
NOTE: I Have no control over the C# code. I need to adapt the JS code around what C# is returning
This is the Javascript code:
console.log('Testing rounding -- js')
nrt = 34622
c = 0
if (nrt <= 5000) c = nrt * 0.405
else if (nrt > 5000 && nrt <= 20000) c = 2025 + ( (nrt - 5000) * 0.291)
else if (nrt > 20000 && nrt <= 50000) c = 6390 + ( (nrt - 20000) * 0.24)
else c = 13590 + ( (nrt - 50000) * 0.18)
var p = nrt * 0.1125
var t = c + p
console.log(t)
console.log(t.toFixed(2))
Result:
Testing rounding -- js
13794.255
13794.25
This is the C# code:
using System;
namespace sample1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Testing rounding -- csharp");
decimal nrt = 34622;
decimal c = 0;
if (nrt <= 5000) c = nrt * (decimal) 0.405;
else if (nrt > 5000 && nrt <= 20000) c = 2025 + ( (nrt - 5000) * (decimal) 0.291);
else if (nrt > 20000 && nrt <= 50000) c = 6390 + ( (nrt - 20000) * (decimal) 0.24);
else c = 13590 + ( (nrt - 50000) * (decimal) 0.18);
decimal p = nrt * (decimal) 0.1125;
decimal t = c + p;
Console.WriteLine(t);
Console.WriteLine(Decimal.Round(t, 2));
}
}
}
Result:
Testing rounding -- csharp
13794.2550
13794.26
Please note that I don't know C# at all. I realise that it has a "decimal" type, which is a 128-bit data type suitable for financial and monetary calculations. It has 28-29 digit Precision
As far as I know, Javascript doesn't handle a 128-bit data type.
I also wonder whether the problem might well be in different implementation of rounding.
I am writing this as I also add that 13794.2550 is spectacularly hard to round reliably across systems. This is a whole different rabbit hole.
But, for example using a rounding function blatantly stolen from stackoverflow:
function r(n, decimals) {
return Number((Math.round(n + "e" + decimals) + "e-" + decimals));
}
console.log(r(13794.2550,2))
console.log(13794.2550.toFixed(2))
Result:
13794.26 <--- this is what I want! But, is it reliable?
13794.25
The rounding function seems to give out the same result. So, maybe I am having a "rounding implementation" problem, rather than a "not enough precision" problem. But, is it reliable?
(That is, is the c# Decimal.Round function implemented exactly as the rounding function blatantly stolen from stackoverflow?