29

Is it possible to change the precision for Decimal numbers in C# globally ?

In TypeScript I am using the framework Decimal.js, where I can change the precision of the Decimal operations globally like so Decimal.set({ precision: 15}). This means that the operation will return at most 15 decimal digits.

  • TypeScript:the operation 5/3 returns 1.66666666666667
  • C# the operation5m/3m returns 1.6666666666666666666666666667

Is there some similar setting for Decimal values in C# ? How can I accomplish this in C# ?

Devid
  • 1,823
  • 4
  • 29
  • 48
  • No, there is no way to globally set an arbitrary precision of `decimal`. – InBetween Jan 11 '18 at 16:59
  • 1
    Do you want to display it with less digits but calculate with all digits or do you need to round stuff? – Patrick Artner Jan 11 '18 at 17:03
  • 1
    @Zorkind Well it depends on the scale factor...unit could theoretically be market value of Apple in billions of dollars, and someone who has a share quantity of 0.1% might want to know up to the last penny how much its worth. Don't assume information you don't know anything about, chances are you'll be wrong. – InBetween Jan 11 '18 at 17:06
  • @PatrickArtner I want that the digits don't exceed the precision that I specified. The perfect solution would be something similar as how Decimal.js does it. Otherwise every proposition is welcome. – Devid Jan 11 '18 at 18:38
  • 1
    decimal.Round(123.123456789m, 6); is designed to round to specific number of places. – Mariusz Nov 03 '22 at 15:09

3 Answers3

33

This isn't exactly what you're asking, but you could initialize a NumberFormatInfo object within the global scope and use it to format decimals. Here is an example:

using System.Globalization;

NumberFormatInfo setPrecision = new NumberFormatInfo();    
setPrecision.NumberDecimalDigits = 2;    
decimal test = 1.22223;

Console.Write(test.ToString("N", setPrecision)); //Should write 1.23

setPrecision.NumberDecimalDigits = 3;
test = 5m/3m;

Console.Write(test.ToString("N", setPrecision)); //Should write 1.667

MSDN Link: https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo(v=vs.110).aspx

NumberDecimalDigits usage example: https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numberdecimaldigits(v=vs.110).aspx

Aage
  • 5,932
  • 2
  • 32
  • 57
Jacob Barnes
  • 1,480
  • 1
  • 12
  • 29
17

There is no generic setting for decimal precision. Your best chance is implementing these methods in your extensions.

var decimalValue = 5m/3m;
var str = decimalValue.ToString("0.##############");//1.66666666666667

or you could use Round;

var decimalValue = 5m/3m;
decimalValue = decimal.Round(decimalValue, 6, MidpointRounding.AwayFromZero);
lucky
  • 12,734
  • 4
  • 24
  • 46
  • https://stackoverflow.com/questions/6739340/format-a-decimal-using-at-least-2-places-and-at-most-6-places/6739384 – Barry Kaye Jan 11 '18 at 17:10
9

The documentation of Decimal.js states the following:

precision

The maximum number of significant digits of the result of an operation.

All functions which return a Decimal will round the return value to precision significant digits except Decimal, absoluteValue, ceil, floor, negated, round, toDecimalPlaces, toNearest and truncated.

Well, if you really need that behavior globally, then simply implement a wrapper type that does that, you've got a good specification to go by:

public struct RoundedDecimal
{
    public static int Precision { get; private set; }

    public static Decimal AbsoluteValue(
        RoundedDecimal d) => Math.Abs(d.value);

    //same with ceiling, floor, etc.

    private readonly decimal value;

    public RoundedDecimal(decimal d)
    {
        value = Decimal.Round(d, Precision);
    }

    public static void SetPrecision(int precision)
    {
        Precision = precision; /*omitted argument validation*/ }

     public static implicit operator Decimal(
         RoundedDecimal d) => d.value;

    public static explicit operator RoundedDecimal(
        decimal d) => new RoundedDecimal(d);

    public static RoundedDecimal operator +(
        RoundedDecimal left, RoundedDecimal right) =>
           new RoundedDecimal(left.value + right.value);

    //etc.
}

Performance wise this will not be very impressive but if its the behavior you need then, by all means, implement it!

DISCLAIMER: written code on my cell phone, so its bound to have bugs... simpy trying to get the idea across.

InBetween
  • 32,319
  • 3
  • 50
  • 90
  • 11
    You must have a pretty big phone.. or micro usb keyboard... this formatting is better than some I've seen written on computers. Well done. – Adrian Jan 12 '18 at 11:06