Округление числа в Javascript так, чтобы оно совпадало с C# - PullRequest
1 голос
/ 28 апреля 2020

У меня есть заявление, написанное на nodejs. Приложение должно рассчитать морской сбор. расчет должен соответствовать результату из порта. Калькулятор сбора в порту написан на C#.

ПРИМЕЧАНИЕ. Я не могу контролировать код C#. Мне нужно адаптировать код JS к тому, что C# возвращает

Это код 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#. Я понимаю, что он имеет «десятичный» тип, который является 128-битным типом данных, подходящим для финансовых и денежных расчетов. Он имеет 28-29 ди ​​git Точность

Насколько я знаю, Javascript не обрабатывает 128-битный тип данных.

Мне также интересно, проблема может заключаться в другой реализации округления.

Я пишу это, также добавлю, что 13794.2550 невероятно сложно надежно округлить в разных системах. Это совершенно другая кроличья нора.

Но, например, с использованием функции округления , явно украденной из 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))

Результат:

13794.26 <--- this is what I want! But, is it reliable?
13794.25

Функция округления, похоже, дает тот же результат. Так что, возможно, у меня проблема с «округлением реализации», а не с «недостаточной точностью». Но надежно ли это?

(то есть функция c# Decimal.Round реализована в точности как функция округления , явно украденная из stackoverflow ?

1 Ответ

2 голосов
/ 28 апреля 2020

Думаю, проблема в том, что вы используете разные типы функций округления.

В разделе JS вы используете toFixed() вместо Math.round(). toFixed - это не то же самое, что C# округление. Это больше похоже на округление C#, когда вы добавляете к нему свойство AwayFromZero. Вы также можете сделать это в C#, но об этом нужно четко сказать -> Math.Round(value, 2, MidpointRounding.AwayFromZero);. Вы должны иметь возможность использовать Math.round(), чтобы получить те же результаты, что и в C#. Они оба поддерживаются Microsoft, поэтому обычно они работают очень похоже и иногда имеют одинаковые реализации библиотек (с точки зрения пользователя).

Math.round (num) vs num.toFixed (0) и несоответствия браузера

Так что да, эта вторая реализация, которую вы использовали, надежна. Если вы беспокоитесь о 128-байтовом преобразовании, попробуйте использовать double вместо decimal и проверьте, есть ли у вас те же результаты, что и у double 64-битный, и если вам нужно дополнительное тестирование, используйте float, который 32-битный .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...