英文:
How can I round up or down a double to one less decimal place than the input has in C#?
问题
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);
}
英文:
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);
}
答案1
得分: 3
为了术语的准确性,我想更严格地定义一下“舍入”。将“将 x 向上舍入到小数点后 n 位”称为“将 x 舍入到 n 位精度”,更具体地意味着“找到大于或等于 x 的最接近的数字,小数点后最多使用 n 位。”其中的“最多”部分实际上很重要,因为“将 10.9991 向上舍入到 3 位精度”将是“11”。
您的问题要求一种方法,该方法将数字舍入为“比输入少一个小数位”,特别是无需告诉该方法输出应具有的精度。其中隐藏着一个问题:数字使用 IEEE 754 中的浮点表示法。
用于存储数字的小数位数可能不是您自然期望的。虽然标准做得很好,但添加具有 2 位小数的数字可能会迅速导致具有“无限”小数位数的数字。考虑这个例子:
var x = 0.0002f;
var x5 = 5 * x;
您可能会惊讶地发现x5
不是0.001
而是0.0009999999
。从float
转到double
在这种情况下会有所帮助,但最终double
也会遇到相同的问题,只是针对不同的值。
那么,您对RoundUp(x5)
的期望是什么?如果值为0.001
,您的期望将是0.01
。但用于表示虚构的0.0009...
的0.0009999999
具有多少小数位呢?即使我们为了争论的缘故说0.0009999999
恰好等于0.00099999990
,从而得出它具有 10 位小数位的结论,那么它向上舍入到 9 位精度意味着在最后的九位上滚动直到到达0.001
,而不是0.01
。
因此,无法通过算法安全地确定给定浮点数在 10 进制中具有多少小数位。因此,您需要向任何函数提供所需的精度,这将引导您到已经存在的代码。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论