Вопрос по c# – Какой тип данных я должен использовать, чтобы представлять деньги в C #?

50

В C #, какой тип данных я должен использовать для представления денежных сумм? Десятичный? Поплавок? Удвоить? Я хочу принять во внимание: точность, округление и т. Д.

Ваш Ответ

5   ответов
0

Decimal& Quot; представлять денежные суммы.

73

System.Decimal:

The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors. The Decimal type does not eliminate the need for rounding. Rather, it minimizes errors due to rounding.

ниSystem.Single (float) ниSystem.Double (double) являютсяprecise enough способен представлять высокоточные числа с плавающей запятой без ошибок округления.

Я проголосовал за это, но я не согласен с окончательным требованием. Это не значит, что float / double недостаточно точны, просто они используют неподходящую основу для денег. Вы могли бы иметь 512-битное значение с плавающей двоичной точкой с более актуальнымprecision чем десятичная дробь - но она все еще не будет подходящей, потому что она не может точно представлять десятичные значения, такие как 0,1.
Моя ошибка - я смешал значения в своем ответе. Я использовал & quot; точный & quot; в моем последнем утверждении не иметь в виду «математическую точность» скорее, чтобы выразить, что округленное число (1 в этом примере) является «менее точным» чем (0.99999_), когда число, присвоенное переменной, было фактически 0.9999_. Плохой выбор слов с моей стороны ...
Я все еще не согласен с вашей последней строкой. Я бы сказал: «Любая система с плавающей запятой, которая опирается на двоичную мантиссу, неспособна представить все десятичные сотые в виде рациональных чисел.
Носредна, вы сталкиваетесь с проблемами здесь, потому что я думаю, что вы неправильно понимаете, что "иррационально" средства. Иррациональность инвариантна относительно выбора базы; точное действительное значение является либо иррациональным, либо оно не равно. Выбор базы не имеет значения. Различие, которое вы действительно хотите провести здесь, не имеет ничего общего с рациональностью, а скорее имеет отношение кrepresentation error.
Вы должны сказать, что любойfinite Система с плавающей запятой с двоичной мантиссой неспособнаexactly представляя все десятичные сотые. То есть,without accruing representation error, Для более подробного анализа основных проблем, связанных с ошибками представления в арифметике с плавающей запятой, вы можете посмотреть серию статей, которые я написал по этой теме:blogs.msdn.com/ericlippert/archive/tags/…
0

Тип денег для CLR, Это пользовательский тип значения (структура), который также поддерживает валюты и обрабатывает проблемы округления.

Никаких README, документов и неофициальных PR от 2-х лет назад ...
Я читал & quot; Адаптивный код через C # & quot; book (с 2014 года) и гласит: «Не рекомендуется использовать десятичный тип для представления валютных значений (...). Вместо этого следует использовать тип значения Money (URL-адрес, аналогичный указанному выше). Я был смущен, поскольку мне всегда говорили использовать десятичную. Автор не спорит, почему мы не должны использовать десятичную дробь. Исходя из этого и того, что написал Джордж, я думаю, что десятичный - это путь.
3

Десятичный это тот, который вы хотите.

2

женными функциями для всех математических операций и операций сравнения в базе 10, поэтому он будет иметь менее существенные ошибки округления. С плавающей точкой (и двойной), с другой стороны, сродни научной нотации в двоичном. В результате десятичные типы более точны, когда вы знаете, какая точность вам нужна.

Запустите это, чтобы увидеть разницу в точности 2:

using System;
using System.Collections.Generic;
using System.Text;

namespace FloatVsDecimal
{
    class Program
    {
        static void Main(string[] args) 
        {
            Decimal _decimal = 1.0m;
            float _float = 1.0f;
            for (int _i = 0; _i < 5; _i++)
            {
                Console.WriteLine("float: {0}, decimal: {1}", 
                                _float.ToString("e10"), 
                                _decimal.ToString("e10"));
                _decimal += 0.1m;
                _float += 0.1f;
            }
            Console.ReadKey();
        }
    }
}

Похожие вопросы