0

我正在尝试为正整数编写一个基本数字计数器(输入一个整数并输出该整数的位数)。这是我的通用公式:

dig(x) := Math.floor(Math.log(x,10))

我尝试dig(x)在 Ruby 中实现等价物,发现当我计算时dig(1000)我得到 2 而不是 3,因为Math.log返回 2.9999999999999996,然后将被截断为 2。处理这个问题的正确方法是什么?(我假设无论用于实现此方法的语言如何,都会发生此问题,但如果不是这种情况,请在您的答案中解释)。

4

3 回答 3

1

要获得整数中位数的精确计数,您可以执行通常的操作:(在 C/C++ 中,假设n为非负数)

int digits = 0;
while (n > 0) {
  n = n / 10; // integer division, just drops the ones digit and shifts right
  digits = digits + 1;
}

我不确定,但我怀疑运行内置对数函数不会比这更快,这会给你一个准确的答案。

我想了一会儿,无法想出一种方法来使基于对数的方法在任何保证的情况下都能工作,并且几乎让自己相信,由于浮点舍入错误,这可能首先是注定的追求,等等

于 2013-12-30T05:48:08.090 回答
0

计算机编程艺术第 2 卷中,我们将在应用 floor 函数之前通过添加一位错误来消除一位错误。

x为 的结果,log然后x += x / 0x10000000为单精度浮点数 (C's float) 做。然后将值传递给floor.

这保证是最快的(假设你有数字形式的答案),因为它只使用几个浮点指令。

于 2013-12-30T05:49:55.983 回答
0

浮点数总是存在舍入误差;这是您在使用它时需要注意并积极管理的危害之一。如果必须使用浮点数,处理它的正确方法是找出预期的累积误差量,并在比较和打印输出中考虑到这一点——适当四舍五入,比较差异是否在该范围内,而不是比较为了平等等等。

例如,没有像 1/10 这样的简单事物的精确二进制浮点表示。

(正如其他人所指出的,您可以重写问题以避免完全使用基于浮点的解决方案,但是由于您专门询问了工作 log() 我想解决这个问题;如果我偏离目标,请道歉。一些其他答案提供了有关如何四舍五入结果的具体建议。这将“解决”这种特殊情况,但随着您的浮动操作变得更加复杂,您必须继续允许在每一步累积舍入并处理每一步的误差或处理累积误差——后者是更复杂但更准确的解决方案。)

如果这对应用程序来说是一个严重的问题,人们有时会使用定标定点来代替(例如,以便士而不是美元来运行财务计算)。或者他们使用以十进制而不是二进制计算的“大数字”包之一;这些都有自己的四舍五入问题,但它们以人类期望的方式四舍五入。

于 2013-12-30T05:50:17.647 回答