【问题标题】:Multiple inner assignments - how it works? [duplicate]多个内部分配 - 它是如何工作的? [复制]
【发布时间】:2015-03-17 17:03:59
【问题描述】:

出于有趣的目的,我正在尝试做一个“1-liner”,但由于某种原因,我无法使代码正常工作。注意:这是 C,而不是 C++,但问题仍然存在。

“展开”版本:

#include <stdio.h>
#include <math.h>

int main() {
    double iter = 1;
    double res = 0;
    double elem = 0;
    double fib_c = 1;
    double fib_p = 1;
    double power = 4;
    double fact = 1;

    while (iter < 15) {
        fib_c += fib_p; //fibonacci current
        fib_p = fib_c - fib_p; //fibonacci previous
        fact *= iter; //factorial
        power *= 4; //power of 4
        elem = (fib_c * power * sqrt(iter+1)) / fact; //element of series
        res += elem; //series

        printf("----\nelem = %2.3f\nres = %2.3f\n", elem, res);

        iter++;
    }

    return 0;
}

这是一个系列(我不知道用英语表示它的数学术语),这里element 从 45 上升到 1264,然后又下降到 47。

这是我正在尝试制作的“包装”版本:

#include <stdio.h>
#include <math.h>

int main() {
    double iter = 1;
    double res = 0;
    double elem = 0;
    double fib_c = 1;
    double fib_p = 1;
    double power = 4;
    double fact = 1;

    while (iter < 15) {
        res += (elem = (fib_c += ((fib_p = fib_c - fib_p)) * (power*=4) * sqrt(iter+1)) / (fact*=iter));

        printf("----\nelem = %2.3f\nres = %2.3f\n", elem, res);

        iter++;
    }

    return 0;
}

这里element 在不到 5 次迭代中超过了整数。很明显,有些事情是错误的。但是什么?

顺便说一句,如果我每次迭代都打印出每个值(fib_cpowerfact),我将看到正确的值(当前斐波那契数、4 的幂、相应的持续阶乘)。所以我猜测“幕后”发生了一些奇怪的事情,我不知道如何管理它。

有什么想法吗?

【问题讨论】:

  • 不要写这样的代码,它是不可维护的,而且附带的好处是不会发生奇怪的未定义行为。快速浏览一下,您正在修改 fib_c 并在同一序列点内读取它,这是经典的 C 未定义行为。见Why are these constructs (using ++) undefined behavior?
  • 正如我所说,“为了好玩”。没有人会在我之后维护代码。
  • @ohyou 未定义的行为不好玩,所以 Shafik 的观点是站得住脚的 ;)
  • @ShafikYaghmour 它正在读取 fib_c 以确定要存储到其中的值。
  • @ShafikYaghmour 这对分析有何影响? fib_c 的两次读取(一个来自+= 和一个来自fib_p = fib_c - fib_p)作为分配给fib_c 的值的计算的一部分发生。第二次读取也是计算分配给fib_p 的值的一部分,不会改变任何东西。

标签: c++ c algorithm micro-optimization


【解决方案1】:
(fib_c += ((fib_p = fib_c - fib_p))

不一样

fib_c += fib_p; //fibonacci current
fib_p = fib_c - fib_p; //fibonacci previous

和这个一样

fib_p = fib_c - fib_p; //fibonacci previous
fib_c += fib_p; //fibonacci current

【讨论】:

  • 哇,谢谢你,不知何故我错过了。如果有人感兴趣,正确的行(就算法而言)是(fib_p = (fib_c += fib_p) - fib_p)
  • “你在 += 运算符的两边都使用了 fib_c”你是认真地声称 i += i; 是 UB 吗?
  • @T.C.,没有。我声称i += (i + 10); 是UB。这是一种预感。我可能弄错了。
  • 扩展为i = i + (i + 10);。那个 UB 怎么样?
  • @T.C.,在阅读了有关序列点和构成 UB 的更多内容后,我得出结论,我的预感是不对的。
猜你喜欢
  • 2020-11-17
  • 1970-01-01
  • 2019-10-02
  • 1970-01-01
  • 2012-05-14
  • 2011-05-26
  • 1970-01-01
  • 2011-05-07
相关资源
最近更新 更多