Decimal vs Double and Other Tips About Number Types in .NET

I've been coding with .NET for a long time. In all of that time, I haven't really had a need to figure out the nitty-gritty differences between float and double, or between decimal and pretty much any other type. I've just used them as I see fit, and hope that's how they were meant to be used.

Until recently, anyway. Recently, as I was attending the AngleBrackets conference, and one of the coolest parts of attending that conference is getting to be in an in-depth workshop. My particular workshop was called I Will Make You A Better C# Programmer by Kathleen Dollard, and my reaction was thus:

One of the most interesting things I learned at Kathleen's session was that the .NET number types don't always behave the way I think they do. In this post, I'm going to walk through a few (a VERY few) of Kathleen's examples and try to explain why .NET has so many different number types and what they are each for. Come along as I (with her code) attempt to show what the number types are, and what they are used for!

The Number Types in .NET

Let's start with a review of the more common number types in .NET. Here's a few of the basic types:

  • Int16 (aka short): A signed integer with 16 bits (2 bytes) of space available.
  • Int32 (aka int): A signed integer with 32 bits (4 bytes) of space available.
  • Int64 (aka long): A signed integer with 64 bits (8 bytes) of space available.
  • Single (aka float): A 32-bit floating point number.
  • Double (aka double): A 64-bit floating-point number.
  • Decimal (aka decimal): A 128-bit floating-point number with a higher precision and a smaller range than Single or Double.

There's an interesting thing to point out when comparing double and decimal: the range of double is ±5.0 × 10−324 to ±1.7 × 10308, while the range of decimal is (-7.9 x 1028 to 7.9 x 1028) / (100 to 28). In other words, the range of double is several times larger than the range of decimal. The reason for this is that they are used for quite different things.

Precision vs Accuracy

One of the concepts that's really important to discuss when dealing with .NET number types is that of precision vs. accuracy. To make matters more complicated, there are actually two different definitions of precision, one of which I will call arithmetic precision.

  • Precision refers to the closeness of two or more measurements to each other. If you measure something five times and get exactly 4.321 each time, your measurement can be said to be very precise.
  • Accuracy refers to the closeness of a value to standard or known value. If you measure something, and find it's weight to be 4.7kg, but the known value for that object is 10kg, your measurement is not very accurate.
  • Arithmetic precision refers to the number of digits used to represent a number (e.g. how many numbers after the decimal are used). The number 9.87 is less arithmetically precise than the number 9.87654332.

We always need mathematical operations in a computer system to be accurate; we cannot ever expect 4 x 6 = 32. Further, we also need these calculations to be precise using the common term; 4 x 6 must always be precisely 24 no matter how many times we make that calculation. However, the extent to which we want our systems to be either arithmetically precise has a direct impact on the performance of those system.

If we lose some arithmetic precision, we gain performance. The reverse is also true: if we need values to be arithmetically precise, we will spend more time calculating those values. Forgetting this can lead to incredible performance problems, problems which can be solved by using the correct type for the correct problem. These kinds of issues are most clearly shown during Test 3 later in this post.

Why Is Int The Default?

Here's something I've always wondered. If you take this line of code:

var number = 5;  

Why is the type of number always an int? Why not a short, since that takes up less space? Or maybe a long, since that will represent nearly any integer we could possibly use?

Turns out, the answer is, as it often is, performance. .NET optimizes your code to run in a 32-bit architecture, which means that any operations involving 32-bit integers will by definition be more performant than either 16-bit or 64-bit operations. I expect that this will change as we move toward a 64-bit architecture being standard, but for now, 32-bit integers are the most performant option.

Testing the Number Types

One of the ways we can start to see the inherent differences between the above types is by trying to use them in calculations. We're going to see three different tests, each of which will reveal a little more about how .NET uses each of these types.

Test 1: Division

Let's start with a basic example using division. Consider the following code:

private void DivisionTest1()  
    int maxDiscountPercent = 30;
    int markupPercent = 20;
    Single niceFactor = 30;
    double discount = maxDiscountPercent * (markupPercent / niceFactor);
    Console.WriteLine("Discount (double): ${0:R}", discount);

private void DivisionTest2()  
    byte maxDiscountPercent = 30;
    int markupPercent = 20;
    int niceFactor = 30;
    int discount = maxDiscountPercent * (markupPercent / niceFactor);
    Console.WriteLine("Discount (int): ${0}", discount);

Note that the only thing that's really different about these two methods are the types of the local variables.

Now here's the question: what will the discount be in each of these methods?

If you said that they'll both be $20, you're missing something very important.

The problem line is this one, from DivisionTest2():

int discount = maxDiscountPercent * (markupPercent / niceFactor);  

Here's the problem: because markupPercent is declared as an int (which in turn makes it an Int32), when you divide an int by another int, the result will be an int, even when we would logically expect it to be something like a double. .NET does this by truncating the result, so because 20 / 30 = 0.6666667, what you get back is 0 (and anything times 0 is 0).

In short, the discount for DivisionTest1 is the expected $20, but the discount for DivisionTest2 is $0, and the only difference between them is what types are used. That's quite a difference, no?

Test 2 - Double Addition

Now we get to see something really weird, and it involves the concept of arithmetic precision from earlier. Here's the next method:

public void DoubleAddition()  
    Double x = .1;
    Double result = 10 * x;
    Double result2 = x + x + x + x + x + x + x + x + x + x;

    Console.WriteLine("{0} - {1}", result, result2);
    Console.WriteLine("{0:R} - {1:R}", result, result2);

Just by reading this code, we expect result and result2 to be the same: multiplying .1 x 10 should equal .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1.

But there's another trick here, and that's the usage of the "{O:R}" string formatter. That's called the round-trip formatter, and it tells .NET to display all parts of this number to its maximum arithmetic precision.

If we run this method, what does the output look like?

By using the round-trip formatter, we see that the multiplication result ended up being exactly 1, but the addition result was off from 1 by a miniscule (but still potentially significant) amount. Question is: why does it do this?

In most systems, a number like 0.1 cannot be accurately represented using binary. There will be some form of arithmetic precision error when using a number such as this. Generally, said arithmetic precision error is not noticeable when doing mathematical operations, but the more operations you perform, the more noticeable the error is. The reason we see the error above is because for the multiplication portion, we only performed one operation, but for the addition portion, we performed ten, and thus caused the arithmetic precision error to compound each time.

Test 3 - Decimal vs Double Performance

Now we get to see something really interesting. I'm often approached by new .NET programmers with a question like the following: why should we use decimal over double and vice-versa? This test pretty clearly spells out when and why you should use these two types.

Here's the sample code:

private int iterations = 100000000;

private void DoubleTest()  
    Stopwatch watch = new Stopwatch();
    Double z = 0;
    for (int i = 0; i < iterations; i++)
        Double x = i;
        Double y = x * i;
        z += y;
    Console.WriteLine("Double: " + watch.ElapsedTicks);

private void DecimalTest()  
    Stopwatch watch = new Stopwatch();
    Decimal z = 0;
    for (int i = 0; i < iterations; i++)
        Decimal x = i;
        Decimal y = x * i;
        z += y;
    Console.WriteLine("Decimal: " + watch.ElapsedTicks);

For each of these types, we are doing a series of operations (100 million of them) and seeing how many ticks it takes for the double operation to execute vs how many ticks it takes for the decimal operations to execute. The answer is startling:

The operations involving double take 790836 ticks, while the operations involving decimal take a whopping 16728386 ticks. In other words, the decimal operations take 21 times longer to execute than the double operations. (If you run the sample project, you'll notice that the decimal operations take visibly longer than the double ones).

But why? Why does double take so much less time than decimal?

For one thing, double uses base-2 math, while decimal uses base-10 math. Base-2 math is much quicker for computers to calculate.

Further, what double is concerned with is performance, while what decimal is concerned with is precision. When using double, you are accepting a known trade-off: you won't be super precise in your calculations, but you will get an acceptable answer quickly. Whereas with decimal, precision is built into its type: it's meant to be used for money calculations, and guess how many people would riot if those weren't accurate down to the 23rd place after the decimal point.

In short, double and decimal are two totally separate types for a reason: one is for speed, and the other is for precision. Make sure you use the appropriate one at the appropriate time.


As can be expected from such a long-lived framework, .NET has several number types to help you with your calculations, ranging from simple integers to complex currency-based values. As always, it's important to use the correct tool for the job:

  • Use double for non-integer math where the most precise answer isn't necessary.
  • Use decimal for non-integer math where precision is needed (e.g. money and currency).
  • Use int by default for any integer-based operations that can use that type, as it will be more performant than short or long.

Don't forget to check out the sample project over on GitHub!

Are there any other pitfalls or improvements we should be aware of? Feel free to sound off in the comments!

Happy Coding!

Huge thanks to Kathleen Dollard (@kathleendollard) for providing the code samples and her invaluable insight into how to effectively explain what's going on in these samples. Check out her Pluralsight course for more!

Why Aren't You Blogging Yet? Tips for Getting Started

I've been writing this blog for about a year and a half now, and I firmly believe that every software professional should write a blog. It's an invaluable tool for connecting with other professionals, for getting your ideas out there, for making bad jokes making good jokes.

I've told this to several other programmers, and I'm always met with the same responses. Wow, you're such a good writer! I can't possibly write as well as you do! Once I've told my ego to calm down and eat a bagel, I start hearing all kinds of excuses: I don't have time, I don't know any good topics, nobody cares about what I have to say. Which is bull, but there you have it.

Writing a blog is not some ancient magic that I studied for years to master! It's a process, one which is becoming a part of me just as much as working or eating is. You can do it too!

Still don't believe me? OK then, let me first dispel some common myths about blogging. All of these are things I have heard from others about why they can't or won't write a blog.

Myths About Blogging

Nobody cares about what I have to say. You're telling me that in a world of 7 billion people, where almost everybody can have someone that looks like them, that no one will ever care about your ideas? I don't believe this for an instant. Someone, somewhere, will have the same problem you have, the same ideas you thought of, and will want to know that someone else out there is thinking the same thing.

I don't have time. Neither do I. I have a family, a career, a house to maintain. But I make time. Writing this blog is now just something I do, rather than something I have to do. My blog is my outlet, my window into new tech and new stories, and my way to communicate with other members of my profession. You can always watch less TV, or play less video games, or find other ways to make time.

I can't write. It's not a requirement to be a writer in order to be a blogger. Half the bloggers out there couldn't write their way out of a contrived plot coincidence wet paper bag! That doesn't stop them, it doesn't stop me, and it shouldn't stop you. Besides, how do you expect to get better if you don't practice? Nobody's asking you to write the next great novel.

I'm scared of what my coworkers/friends/peers will think. Ignore them! If they're gonna change their mind about you because you put yourself out there, do you want to care about their opinion? Nobody gets to influence you more than you.

I don't have any good topics to blog about. Everything you know, someone else doesn't know. Don't assume that because you know something, everyone else does too.

Everything I want to write about has already been written. This doesn't matter at all. Half the topics I blog about have already been blogged about by other people. The trick is to find a way to make it interesting for your readers, make it unique in some way that doesn't In my case, I use humor (to varying effect), simple sentences, and general topics to reach as many people as I can.

Why Should I Blog Anyway?

Glad you asked!

It helps your communication skills. Sitting down and thinking about a problem for long enough allows you to concisely and accurately describe that problem to others. Communication is one of the most (if not the most) important soft skill for developers, and writing blog posts will make you a better communicator.

It gets your name out there. Especially if you have a super common name like I do. Writing a blog gets your ideas out into the world for your friends, coworkers, even prospective employers to see.

It teaches humility. There's been quite a few times where I've screwed something up and some kind soul out there on the interwebs has pointed it out (always with respect, of course).

It teaches you to be thorough. If you're taking the time to write something, you'd better be pretty darn sure it's accurate; or else you'll have a hoard of annoyed internet dwellers ready to explain, in excruciating detail, why and how and where you are wrong. Repeatedly.

Hopefully by now I've got you convinced to try blogging out (or, at least not actively hostile to the idea). Here's a couple of tips for getting started with your very own blog.

Tips For Getting Started

Get your own domain name. Your own, custom domain name makes it much easier for people to find and refer back to your blog, plus it looks professional. I personally think the top-level domain (TLD, e.g. .net, .com, .whatever) doesn't matter at all, but I'd still get something people recognize.

Start small. Pick a small topic, write a clear, concise post about it, and post it.

Don't write novels. I've seen other bloggers recommend writing everything about a topic on one page, but for me (probably because I'm a distracted individual) seeing a huge wall of text on a page is cause for me to run screaming in terror (aka hitting the back button). If the topic is large, break it up into multiple posts.

Post often. I personally write at least one post per week. They don't have to be big, involved works; hell they don't even have to be good, just write something. The post you've published is better than the post you've written.

Use whitespace. Huge multi-sentence paragraphs are a big turn off to many readers; they look impenetrable, dense, scary. Use whitespace by making lots of small paragraphs, and cut out any words or sentences that don't clearly and concisely support the point you are making.

Allow comments. It boggles my mind that bloggers can write some huge, insightful post and not allow other people to leave comments on it. Comments are where much of the value in writing a blog lies! After all, the whole of humanity is generally going to be smarter than you.

Manage the comments. Of course, allowing comments means some extra work on your part. You have to make sure you don't allow spam, or ads, or abusive posters. But in my opinion the extra work involved in maintaining a comments section is heavily outweighed by the value it provides.

Make it something you just do. If you want your blog to be successful, make it something you do, rather than something you have to do. This is the truly difficult part of writing a blog, but that kind of commitment tends to shine through your writing, making it obvious that blogging is something you enjoy rather than tolerate.

Don't expect to make money, because you probably won't. Blogging is not something people do to make a living. Sure, some super-famous bloggers can do this, but for the vast majority of us we're lucky if we make enough money to pay our hosting costs. Don't blog if all you're after is money, because you'll be sorely disappointed.

I love writing. It's why I write stories, why I write tutorials, why I write at all. But you don't have to love to write to be a good blogger, and you certainly don't need to be a good writer to be an effective blogger (proof). To me, the benefits of blogging significantly outweigh the downsides, and the skills writing teaches (communication, humility, confidence) are useful in almost every facet of our lives, not just our professional one.

So go get started! Nothing's stopping you except you!

Happy Coding Writing!

Getting All Valid Enum Values in ASP.NET Web API

One of the commenters on my blog posed an interesting question on my article about serializing enumerations in Web API:

A comment on my blog, asking

He wanted to know how someone who is querying a Web API might know what possible values a given enumeration has. I didn't answer that in the post he commented on, so I'll do that now. How do we tell consumers what possible values an enumeration in a Web API app has?

Let's say we have the following enums:

public enum AddressType  

public enum AccessLevel  

We want to expose a query which returns these values for each enumeration. To do that, let's create a class for EnumValue:

public class EnumValue  
    public string Name { get; set; }
    public int Value { get; set; }

It's a pretty generic class, to be sure, but since all enumerations are is a name and a value it serves our purposes well enough.

The trick now is to create an extension which uses Reflection to get all the names for the given enum. In fact, we can even make that method generic, so it can be used for any enumeration at all.

public static class EnumExtensions  
    public static List<EnumValue> GetValues<T>()
        List<EnumValue> values = new List<EnumValue>();
        foreach (var itemType in Enum.GetValues(typeof(T)))
            //For each value of this enumeration, add a new EnumValue instance
            values.Add(new EnumValue()
                Name = Enum.GetName(typeof(T), itemType), 
                Value = (int)itemType
        return values;

Finally, we can use Web API methods that call this extension:

public class HomeController : ApiController  
    public IHttpActionResult GetAccessLevels()
        return Ok(EnumExtensions.GetValues<AccessLevel>());

    public IHttpActionResult GetAddressTypes()
        return Ok(EnumExtensions.GetValues<AddressType>());

When we call this method using Postman, we now get an appropriate response code (200 OK) and the data we were looking for. Here's the address types:

A Postman response, showing the three possible values for the enumeration AddressType

And here's the access levels:

A Postman response, showing the three possible values for the enumeration AccessLevel

Of course, this is just one of many possible solutions to this particular problem. I like this method because it's generic and reusable for all enumerations, but if you find a better method, please feel free to share in the comments!

That's all there is to it! Now any consumer can hit these methods and know exactly what values can be used for the AccessLevel and AddressType enumerations!

I also have a repository over on GitHub which stores the sample code for this post. Check it out!

Happy Coding!

Being a Better Lead Developer

I've mentioned before that I'm what my company calls a "lead" developer, which means I'm in charge of projects, not people. It is my responsibility to assign work, conduct code reviews, divvy up tasks, etc. It may sound like this position means doing a lot of paperwork (and, in fairness, sometimes it means exactly that) but for the most part I love my job.

That said, leadership is not a quality you are born with, as I can personally attest to. For most of my school days and the first five years of my professional career, I was the opposite of a leader; a loner, content to lurk all day in my ivory tower and only emerge when I'd solved some problem, be it calculus or my essay for English class. I didn't listen to others, I was never wrong, I didn't ask why because I already "knew" the answer. I was the classic nerd, the anti-social, sci-fi loving, helps-all-the-people-with-their-homework-but-never-gets-a-date 80's-movie geek. I'm still that guy to some degree.

Four years ago, I was laid off from a job I didn't particularly like and my whole viewpoint changed irrevocably. I had felt like I had no control in that situation, and I was sick of being only a sidekick in my game of life and not the main player. I needed to do something else, something fulfilling, and I slowly came to realize that for me, being a teacher was what I liked to do. I'd truly enjoyed assisting my classmates with their schoolwork, and now I wanted to help others.

A presenter points toward code on a screen Teacher, information and computer science by Wonderlane, used under license.

Two years ago, an opportunity arose in my organization for a lead developer role, and I quickly volunteered. I had no previous leadership experience, and up until that point becoming anything other than a code monkey hadn't even been a consideration for me. But I saw my opportunity to teach, to guide, to help, and I grabbed it and didn't let go. Finally I had some measure of control back.

Since I haven't been either fired or demoted in the time that I've been a lead, I can conclude that I'm doing an acceptable job. I think. At any rate, while I've found this position largely to my liking, there's been a few things I needed to learn on the way. In my case, four ideals have helped me become a better lead developer and could help out those of you who might wish to be (or already are) a leader of some kind in your organization. I try to keep these ideals in mind every day I'm at my desk.

So what are they? Glad you asked!

Delegation Is Your Friend

There's only one of me (as far as I know), and as such if I ever wanted to have time to do something else I had to consciously try to not do everything myself. After all, what good are having teammates if you never give them anything to do?

A to-do list Tuesday to-do list by Stacy Spensley, used under license.

When I was promoted to lead, I kept thinking in terms of my time. Oh, I know this project, this will only take a couple hours which promptly fell apart because I was already stretched too thin. Sixteen two-hour tasks that are all due tomorrow are too many balls in the air for one programmer to juggle, no matter how capable they think they are. I was forced to start giving some of my balls away to trusted, capable members of my team...

Are we done giggling now? Good.

As I was saying, we can't do everything by ourselves, so we have to trust others to do some of it for us. Trust is the hard part; it takes a while to be able to trust anyone with something we give them. But once that trust is established, we'll be able to assign tasks and code to our teammates and know that they'll get it done correctly, efficiently, completely.

You can't do it all yourself; delegation is your friend.

Listen Up

Ever woken up in the middle of a conversation and realized that you had no idea what the other person was saying? (If you have: just smile and nod. Eventually they will leave.) This is something we should not ever do when talking with your teammates. They are our eyes and ears into the code that you may not be personally familiar with; you need them to squash bugs and implement features and run tests that you may not be very skilled at doing, or even able to do at all. But if we are to hear what they are telling us, we need to be able to listen to them.

A drawing of differently-colored ears, above each of which is a letter in the word Listen by Ky, used under license.

This is a particularly difficult thing for me because listening requires focus, but practice has slowly improved my ability to concentrate and fully comprehend what others are saying. If someone is talking at me, it is my job to ensure that they are also talking to me; communication is a two-way street. To do this, I follow two guidelines:

  1. Look at their eyes. This forces me to pay attention to what they are saying.
  2. Mentally repeat back what they just said. I find that repetition helps me retain knowledge, so forcing me to repeat to myself what the other person just said is invaluable in helping me digest what it means.

This was wildly uncomfortable for a natural introvert like me when I first started, but as I kept at it I slowly got acclimated to actually looking at people and remembering what they were saying. It's still tough to focus during some conversations (particularly when the topic at hand is contentious or difficult to talk about) but I'm getting better. I truly believe that you cannot be a good leader without being a good listener.

Listen to those around you, and pay attention to what they are saying.

Since I see that you are nodding in agreement (I'm glad we see eye-to-eye on this) I'll move right along.

Be Willing to Be Wrong

Pssh. Whatever. I'm never wrong! It's you guys who are wrong, not me!

An angry-looking housecat, with the phrase Modified from angry tiger by Jaqen, used under license

If you know a programmer that acts like this, you have my permission to slap them. Hard. Repeatedly, if necessary.

We must be willing to entertain the idea that we are wrong at all times. If we constantly believe that we could be mistaken, we become more willing to consider other points of view, other ideas. Part of listening and comprehending is the ability to consider someone else's opinion with the same weight as our own. If we're never wrong, can anybody else ever be right?

Here's an example: say you assign a small bug to one of your junior developers. You give them directions about how to reproduce the bug and how to fix it, and send them off on their way. A little while later, they submit their changes for code review, but when you look over their solution you find that they ignored your counsel and squashed the bug a different way. As it turns out, an objectively better way.

Some programmers would be annoyed that the junior didn't heed their advice, and those people make terrible leads. Ingenuity and creativity are to be celebrated, encouraged, and wasting time being upset that some punk didn't take your obviously sublime advice to heart doesn't help us deliver a product; in fact, it does just the opposite, because now you'll waste time trying to persuade the junior that your way is the One True Way TM rather than getting anything done.

Be willing to be wrong, so that you can objectively consider the possibility that others may be right.

Use The Most Powerful Word

There's a fine line to walk, though, since if we got to a lead position it is unlikely we will be wrong all of the time. This is where the most powerful word, the most important question we can ever ask comes in handy. It's so simple that many adults simply forget to use it at all, but five-year-olds use it all the time.


Why did you choose to do it that way, instead of the way I told you to do it? Why are these requirements part of this sprint? Why does the button need to be on the right instead of centered in the div? Why does our team sit on this floor rather than the other, and why do we not all sit together?

A reporter raises his hand to ask a question at a press conference Reporter raising hand at US Army press conference, used under license

The reasoning is simple: questions lead to answers, answers lead to understanding, and understanding is your responsibility as a lead. Our focus needs to be the bigger picture: how all of the individual stories or tasks fit together, how the end user expects the application to work, how the team will get from A to B during the development process. We need to understand the scope of what we are trying to accomplish in order to actually accomplish it.

Before understanding, though, comes questioning. Ask why, early and often, and don't quit until you get some kind of an answer, especially if it's an answer you don't like, because those kinds of answers are gateways to either comprehension (meaning you are wrong) or clarification (meaning the other person is wrong). Don't be arrogant, don't be brash, just be kind but persistent and you'll get an answer.

Question everything!

Why should I listen to you?

Glad you're already asking the important questions.

You shouldn't listen to me! At least, not without trying some of these things for yourself. I'm just some guy on the internet. But I have been a lead developer for two years, I haven't screwed it up yet, and these four things - delegation, listening, willingness to be wrong and asking "why?" - have been instrumental in my constant quest to learn, to understand, to become a better developer. Maybe, hopefully, they'll help you as well.

And if they don't, well, just smile and nod. Often that gets the job done too.

A diagram, showing a Boss vs leader by John Lester, used under license.