舍入 Javascript 中的数字,使其与 C# 匹配
Rounding a number in Javascript so that it matches C#
我有一个用 nodejs 编写的应用程序。该应用程序需要计算海事税。计算需要与端口的结果相匹配。港口的征费计算器是用C#写的
注意:我无法控制 C# 代码。我需要围绕 C# 返回的内容调整 JS 代码
这是 Javascript 代码:
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))
结果:
Testing rounding -- js
13794.255
13794.25
这是 C# 代码:
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));
}
}
}
结果:
Testing rounding -- csharp
13794.2550
13794.26
请注意,我根本不懂 C#。我意识到它有一个 "decimal" 类型,这是 适合金融和货币计算的 128 位数据类型。它有 28-29 位精度
据我所知,Javascript 不处理 128 位数据类型。
我也想知道问题是否可能出在不同的舍入实现上。
我写这篇文章是因为我还补充说 13794.2550 非常难以跨系统可靠地舍入。这是一个完全不同的兔子洞。
但是,例如使用 rounding function blatantly stolen from Whosebug:
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))
结果:
13794.26 <--- this is what I want! But, is it reliable?
13794.25
四舍五入函数似乎给出了相同的结果。所以,也许我遇到的是 "rounding implementation" 问题,而不是 "not enough precision" 问题。但是,靠谱吗?
(即c#Decimal.Round函数的实现是否和rounding function blatantly stolen from Whosebug一模一样?
我认为您遇到的问题是因为您使用了不同类型的舍入函数。
在 JS 部分,您使用的是 toFixed()
而不是 Math.round()
。 toFixed 与 C# 舍入不完全相同。它更类似于向其添加 AwayFromZero
属性 的 C# 舍入。您也可以在 C# 中执行此操作,但必须明确说明 --> Math.Round(value, 2, MidpointRounding.AwayFromZero);
。您应该能够使用 Math.round()
获得与在 C# 中相同的结果。它们都由 Microsoft 维护,因此通常它们的工作方式非常相似,有时具有相同的库实现(从用户的角度来看)。
Math.round(num) vs num.toFixed(0) and browser inconsistencies
是的,您使用的第二个实现是可靠的。如果您担心 128 字节的转换,请尝试使用 double
而不是 decimal
并检查结果是否与 double
是 64 位相同,如果您需要进一步测试,请使用 float
即 32 位。
我有一个用 nodejs 编写的应用程序。该应用程序需要计算海事税。计算需要与端口的结果相匹配。港口的征费计算器是用C#写的
注意:我无法控制 C# 代码。我需要围绕 C# 返回的内容调整 JS 代码
这是 Javascript 代码:
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))
结果:
Testing rounding -- js
13794.255
13794.25
这是 C# 代码:
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));
}
}
}
结果:
Testing rounding -- csharp
13794.2550
13794.26
请注意,我根本不懂 C#。我意识到它有一个 "decimal" 类型,这是 适合金融和货币计算的 128 位数据类型。它有 28-29 位精度
据我所知,Javascript 不处理 128 位数据类型。
我也想知道问题是否可能出在不同的舍入实现上。
我写这篇文章是因为我还补充说 13794.2550 非常难以跨系统可靠地舍入。这是一个完全不同的兔子洞。
但是,例如使用 rounding function blatantly stolen from Whosebug:
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))
结果:
13794.26 <--- this is what I want! But, is it reliable?
13794.25
四舍五入函数似乎给出了相同的结果。所以,也许我遇到的是 "rounding implementation" 问题,而不是 "not enough precision" 问题。但是,靠谱吗?
(即c#Decimal.Round函数的实现是否和rounding function blatantly stolen from Whosebug一模一样?
我认为您遇到的问题是因为您使用了不同类型的舍入函数。
在 JS 部分,您使用的是 toFixed()
而不是 Math.round()
。 toFixed 与 C# 舍入不完全相同。它更类似于向其添加 AwayFromZero
属性 的 C# 舍入。您也可以在 C# 中执行此操作,但必须明确说明 --> Math.Round(value, 2, MidpointRounding.AwayFromZero);
。您应该能够使用 Math.round()
获得与在 C# 中相同的结果。它们都由 Microsoft 维护,因此通常它们的工作方式非常相似,有时具有相同的库实现(从用户的角度来看)。
Math.round(num) vs num.toFixed(0) and browser inconsistencies
是的,您使用的第二个实现是可靠的。如果您担心 128 字节的转换,请尝试使用 double
而不是 decimal
并检查结果是否与 double
是 64 位相同,如果您需要进一步测试,请使用 float
即 32 位。