-2

I have two values and I want to round them like this. How can I do this for one less decimal place than the input has with math methods in C#?

100.67 -> 100.7 -- up

100.67 -> 100.6 -- down

50.563 -> 50.57 -- up

50.563 -> 50.56 -- down

I tried this code block, but it didn't work like I want. I don't want to give a precision for rounding. Whatever the decimal value is, I need to round it up or down.

public double RoundDown(double number, int decimalPlaces)
{
    return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}

public double RoundUp(double number, int decimalPlaces)
{
    return Math.Ceiling(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}
LWChris
  • 3,320
  • 1
  • 22
  • 39
zedge08
  • 31
  • 1
  • 3
    Does this answer your question? [How to round up or down in C#?](https://stackoverflow.com/questions/13482159/how-to-round-up-or-down-in-c) – GSerg Apr 17 '23 at 09:04
  • 2
    @zedge08 I think I understand that you are looking for a way to round to "one less decimal place than the input has"? If yes, please edit your question to clarify this, and highlight especially that you are looking for a solution where you don't have to manually give the precision. This would be a question that can be answered (although I may foreshadow that the answer is probably not quite what you are hoping for, since the oddities of floating-point-arithmetic makes this a much less trivial problem than you might realize so far). – LWChris Apr 17 '23 at 11:01
  • If I understand correctly, you want to write a method to round up (or down) a double value of arbitrary precision by a single decimal position ? – Alex Apr 17 '23 at 11:48
  • @Alex yes you got it right but it is valid for every decimal position. – zedge08 Apr 17 '23 at 12:29
  • Some more insidious values are boundary ones like 100.65, 50.565, 100.05, and 50.005 (and depending on the underlying (machine) representation of them). – Peter Mortensen Apr 19 '23 at 08:37
  • This question is discussed in [meta](https://meta.stackoverflow.com/questions/424253/how-should-i-proceed-if-my-re-open-vote-was-rejected-although-the-issues-are-fix) – TheMaster Apr 19 '23 at 11:31
  • [1/2] `c#` is not my *Area of Expertise* (I came here from the 'Meta' Thread), but I still find this Qt "unclear", with 1 Answer provided (based on several Assumptions that should be clearly defined in the Qt...). => "*I have two values*" is probably irrelevant, you want for any Input Value 2 Outputs, the `RoundUp` + `RoundDown` with `n*Dec -1`. // => Define where your Input Values come from: Do they always have [2-3] Decimals...?, – chivracq Apr 20 '23 at 01:52
  • [2/2] ... or define those 2 Nb's. Can they be `100.33333333...` or `50.99999999....` (coming from a Fraction)...?, => can you *force* 4 or 6 Decimals...? (=> `100.3333` or `50.9999` would *invalidate* @LWChris's Answer, etc...) :idea: – chivracq Apr 20 '23 at 01:52

1 Answers1

3

For the sake of terminology, I want to define "rounding" a bit more rigorous here. "Rounding up x to n decimal places" will be called "Rounding up x to a precision of n places", and will more specifically mean "Finding the closest number greater than or equal to x that uses at most n places behind the decimal point." The "at most" part is actually important, because "rounding 10.9991 up to a precision of 3 places" will be "11".

Your question asks for a method that rounds to "one less decimal place than the input", specifically without the necessity to tell that method the precision the output is supposed to have. Therein lies a hidden problem: numbers using floating point representation according to IEEE 754.

The number of decimal places used to store a number may not be what you would naturally expect. While the standard does a really good job, adding numbers with 2 decimal places may quickly result in a number with "infinite" decimal places. Consider this example:

var x = 0.0002f;
var x5 = 5 * x;

It may surprise you to learn that x5 is not 0.001 but 0.0009999999. Going to double from float helps in this case, but ultimately double will suffer from the same problem, just for different values.

So, what is your expectation for RoundUp(x5)? If the value was 0.001, your expectation would be 0.01. But what is the number of decimal places for 0.0009999999 which represents a fictional 0.0009... with infinite decimal places? And even if we say 0.0009999999 was exactly equal to 0.00099999990 for the sake of argument, and thereby conclude it has 10 decimal places, then it rounding up to a precision of 9 places means rolling over the nines at the end until we arrive at 0.001, not 0.01.

Therefore, it is impossible to algorithmically safely determine "how many decimal places" a given floating point number has in base 10. Therefore you need to provide the desired precision to any function, which will lead you to the code you already have.

LWChris
  • 3,320
  • 1
  • 22
  • 39