【问题标题】:Fractional Part of the number question数字问题的小数部分
【发布时间】:2009-05-17 19:02:24
【问题描述】:

在不使用内置天花板或地板功能的情况下,确定添加/减去数字所需的必要分数以便将其四舍五入为最接近的整数的好算法是什么?

编辑:寻找一个数学数字技巧来计算将数字四舍五入到最接近的整数所需的部分。数学运算越原始越好。请避免使用其他程序。无论哪种方式适合您的方法,都可以采用 0.5。这不是我的家庭作业问题,我也不打算在任何地方使用它。

【问题讨论】:

  • 您可以使用标准 api 中的其他功能吗?或者你真的想实现自己的算法,即使这意味着重新实现轮子?
  • 是否可以转换为 int?或者这算作内置的地板功能吗?
  • 这是否也排除了最近的整数函数 nint()?
  • 你能解释一下为什么你想要/需要这样一个算法吗?
  • 你将如何处理 0.5,它与 0 和 1 等距。算术舍入总是向上舍入,但银行家的舍入取最接近的偶数。

标签: math rounding floor ceil


【解决方案1】:

将数字加一得到小数部分,如果>0.5,则向上取整,否则向下取整

将数字除以0.5,如果是奇数,则向上舍入,否则向下舍入

【讨论】:

  • 请注意,有些语言只对整数定义 mod/%。
  • 算法很聪明 if x %1 >= 0.5 print ((x- x%1) + 1) -x else print x%1 end 你能想出没有%的另一种解决方案吗?
  • 为什么?没有任何其他信息是不可能回答这个问题的
  • 您还需要什么信息?我在同一条线上思考。必须有一个简洁的数学程序来解决这个问题。没有任何其他约束。只需找出将数字四舍五入到最接近的整数所需的部分。数学运算越原始越好。
  • 为什么乘以二不起作用?如果您想要更原始的操作,请将数字添加到自身
【解决方案2】:

一旦有了数字的小数部分,问题就基本解决了。获得小数部分的一种方法是从您的数字中反复减去 2 的幂(假设它已被设为正数,如果一开始为负数)。

下面的函数,getWholeMaker,返回你想要的(必须添加到四舍五入的“东西”)。它的运行时间是O(log(n)),并且只使用基本操作。

/* Returns the factional part of x */
double getFrac(double x) {
    if(x < 0) x = -x;
    if(x < 1) return x;
    else if(x < 2) return x-1;

    /* x >= 0 */
    double t = 2;
    while(t+t <= x) t += t;
    /* t is now the largest power of 2 less than or equal to x */
    while(t >= 1) {
        if(t <= x) x -= t;
        t /= 2;
    }

    return x;
}

double getWholeMaker(double x) {
    double frac = getFrac(x);
    double sign = x >= 0 ? +1 : -1;
    return sign * (frac <= 0.5 ? -frac : 1-frac);
}

【讨论】:

  • 甜蜜。但这看起来像是优化了 pkaeding 的算法。我说的对吗?
  • 是的,它就像 pkaeding 的,但工作在对数时间(pkaeding 是线性时间)。
【解决方案3】:

如果你不能使用 mod(因为它可能只为你的语言中的整数定义,你也许可以做这样的事情(在 C-ish 伪代码中):

// make the input positive:
boolean inputPositive = true;
if (input < 0) {
  input = 0 - input;
  inputPositive = false;
}

// subtract 1 until you just have the decimal portion:
int integerPart = 0;
while (input > 1) {
  input = input - 1;
  integerPart++;
}

int ret;
if (input >= 0.5) { // round up
  ret = integerPart + 1;
} else {
  ret = integerPart;
}

if (inputPositive) {
  return ret;
} else {
  return 0 - ret;
}

此解决方案不使用 mod 或任何外部功能。当然,我无法想象为什么你会在现实生活中想要这个。不过想想还是很有趣的。

【讨论】:

  • 在我看来非常好的答案,它符合所有要求! :-)
  • +1。您可以通过减去更小的 2 次方来对此进行改进,这样对于较大的输入,此过程也将在合理的时间内终止。
  • 这很有趣。我喜欢你检查数字是否为正的部分。我没想过。我曾希望有人会提供数学技巧,即使减去一个非常乏味,我认为这个解决方案是有效的。谢谢。
猜你喜欢
  • 2013-06-08
  • 2017-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 1970-01-01
  • 2021-09-14
相关资源
最近更新 更多