Is casting an int to double and back safe

Viewed 1069

Is it safe to cast an Integer to Double and back again?

To be a bit more specific, is it true for all integers that originalValue equals retrievedValue in the following scenario:

int originalValue = 42;
double backingField = (double)originalValue;
int retrievedValue = (int)backingField;

A bit of background/motivation: I am writing lots of micro services in C# with lots of interfaces. For a time interval in seconds, some clients send them as integers, others as floating values. I need to store them and return the same value as the client sent me. My question targets, if it is safe to assume, that when I retrieve an integer, but store all values as double that a cast to integer on the retrieving client will always return the original value. Especially as casting is done by truncating any values after the comma.

Can any cast to double result in a value lower than the integer, e.g. 42 -> 41.9999999999999?

2 Answers

Simply casting just strips everything past the decimal point. I know you probably don't need to do any rounding, but just to make this answer more complete, here's the scoop on it. To round up or down, you can use the Math.Round() method. This will round up or down and provides a parameter on what to do if its midway. You could also use the Math.Floor() or Math.Ceiling() methods to implicitly round up or round down prior to casting. Here are some examples:

double num1 = 3.5;
double num2 = 3.2;
double num3 = 3.9;

(int)num1 // returns 3;
(int)num2 // returns 3;
(int)num3 // returns 3 also;
(int)Math.Round(num1) // returns 4
(int)Math.Round(num2) // returns 3
(int)Math.Round(num3) // returns 4
(int)Math.Floor(num1) // returns 3
(int)Math.Floor(num2) // returns 3
(int)Math.Floor(num3) // returns 3
(int)Math.Ceiling(num1) // returns 4
(int)Math.Ceiling(num2) // returns 4;
(int)Math.Ceiling(num3) // returns 4;

There are predefined implicit conversions from int to long, float, double, or decimal. As put,

Any integral type is implicitly convertible to any floating-point type.

Check Implicit numeric conversions table (C# Reference) on ms docs.

Then, for the inverse operation

Precision but not magnitude might be lost in the conversions from int to float.

Float to double is an implicit cast also.

You might use a technique similar to testing frameworks asserting equality for numerical types with a tolerance.

To my detractors (edit)

Linked to your microservices issues, quoting Sam Newman on this

Be liberal in what you accept, conservative in what you send.

If you have a client requiring say, integers, store your data as double, or decimal, and use some mechanism to prevent loss of precision when casting to int, like Math.Floor or Math.Ceiling with proper rounding options. Else if another client requires some format for which there's an implicit cast with no loss of precision, you're off easy.

Related