Правильно округлить финансовые данные - PullRequest
3 голосов
/ 16 марта 2012

Я решил воссоздать свой вопрос:

decimal dTotal = 0m;
foreach (DictionaryEntry item in _totals)
    {
        if (!string.IsNullOrEmpty(item.Value.ToString()))
        {
            dTotal += Convert.ToDecimal(item.Value);
        }
    }
    Console.WriteLine(dTotal / 3600m);
    Console.WriteLine(decimal.Round(dTotal / 3600m, 2));
    Console.WriteLine(decimal.Divide(dTotal, 3600m));

Приведенный выше код возвращает:

579,99722222222222222222222222

580,00

579,99722222222222222222222222

Итак, вот откуда мои проблемы, мне действительно нужно просто отобразить 579.99; но любой раунд, будь то decimal.Round или Math.Round, все равно вернется 580; даже строковые форматы для {0:F} return 580.00.

Как мне правильно это сделать?

1 Ответ

10 голосов
/ 16 марта 2012

Новый ответ (на новый вопрос)

Хорошо, значит, у вас есть значение 579.99722222222222222222222222 - и вы хотите, чтобы оно было округлено до двух десятичных знаков. Разве 580.00 не является естественным ответом? Это ближе к первоначальному значению, чем 579,99. Похоже, вы, по сути, хотите поведение flooring , но с заданным количеством цифр. Для этого вы можете использовать:

var floored = Math.Floor(original * 100) / 100;

В этом случае вы можете выполнить оба действия за один шаг:

var hours = Math.Floor(dTotal / 36) / 100;

... что эквивалентно

var hours = Math.Floor((dTotal / 3600) * 100) / 100;

Оригинальный ответ (на оригинальный вопрос)

Звучит так, как будто вы, вероятно, получили payTotal в неподходящей форме для начала:

using System;

class Test
{
    static void Main()
    {
        decimal pay = 2087975.7m;
        decimal time = pay / 3600;
        Console.WriteLine(time); // Prints 579.99325
    }
}

Это проблема:

var payTotal = 2087975.7;

Это присваивает payTotal переменной double. Значение, которое вы на самом деле получили, составляет 2087975,69999999995343387126922607421875, а это не то, что вы хотели. Каждый раз, когда вы обнаруживаете, что кастуете от double до decimal или наоборот, вы должны волноваться: есть вероятность, что вы где-то использовали неправильный тип. Значения валют должны абсолютно храниться в decimal, а не double (и есть другие вопросы о переполнении стека, которые говорят о том, когда и когда использовать).

См. Две мои статьи о числах с плавающей запятой для получения дополнительной информации:

(Как только вы получите правильные результаты, их форматирование, конечно, другое дело, но это не должно быть слишком плохо ...)

...