【问题标题】:Unexpected Results with Functional Programming in CC 函数式编程的意外结果
【发布时间】:2014-10-12 17:26:24
【问题描述】:

在 C 编程中尝试函数式风格时,我尝试将以下 Haskell 代码翻译成 C。

f (0, 0, 0, 1) = 0
f (0, 0, 1, 0) = f (0, 0, 0, 1) + 1
f (0, 1, 0, 0) = f (0, 0, 1, 1) + 1
f (1, 0, 0, 0) = f (0, 1, 1, 1) + 1
f (a, b, c, d) = (p + q + r + s) / (a + b + c + d)
    where
    p
        | a > 0 = a * f (a - 1, b + 1, c + 1, d + 1)
        | otherwise = 0
    q
        | b > 0 = b * f (a, b - 1, c + 1, d + 1)
        | otherwise = 0
    r
        | c > 0 = c * f (a, b, c - 1, d + 1)
        | otherwise = 0
    s
        | d > 0 = d * f (a, b, c, d - 1)
        | otherwise = 0

main = print (f (1, 1, 1, 1))

#include <stdio.h>
#include <stdlib.h>

#define int const int
#define double const double

double f(int a, int b, int c, int d)
{
    if (a == 0 && b == 0 && c == 0 && d == 1)
    {
        return 0.0;
    }
    else if (a == 0 && b == 0 && c == 1 && d == 0)
    {
        return f(0, 0, 0, 1) + 1.0;
    }
    else if (a == 0 && b == 1 && c == 0 && d == 0)
    {
        return f(0, 0, 1, 1) + 1.0;
    }
    else if (a == 1 && b == 0 && c == 0 && d == 0)
    {
        return f(0, 1, 1, 1) + 1.0;
    }
    else
    {
        int p = a > 0 ? a * f(a - 1, b + 1, c + 1, d + 1) : 0;
        int q = b > 0 ? b * f(a, b - 1, c + 1, d + 1) : 0;
        int r = c > 0 ? c * f(a, b, c - 1, d + 1) : 0;
        int s = d > 0 ? d * f(a, b, c, d - 1) : 0;
        return (double)(p + q + r + s) / (double)(a + b + c + d);
    }
}

int main(void)
{
    printf("%f\n", f(1, 1, 1, 1));
    return EXIT_SUCCESS;
}

我期待完全相同的行为,但 C 程序总是输出 0.0。使用f(0, 0, 1, 1),它们都输出 0.5,但是每当数字变得更大时,C 版本就根本不起作用。出了什么问题?

【问题讨论】:

  • 我认为您需要在 C 版本中也将 a,b,c,d 和 p,q,r,s 声明为 double。然后你也可以省略演员表。

标签: c haskell functional-programming purely-functional


【解决方案1】:
int p = a > 0 ? a * f(a - 1, b + 1, c + 1, d + 1) : 0;
int q = b > 0 ? b * f(a, b - 1, c + 1, d + 1) : 0;
int r = c > 0 ? c * f(a, b, c - 1, d + 1) : 0;
int s = d > 0 ? d * f(a, b, c, d - 1) : 0;

这里递归调用f 的结果在存储在 int 变量中时被截断为整数。因此,例如,如果 a 为 1,f(a-1, b+1, c+1, c+1)0.5,则 p 将为 0 而不是 0.5,因为您无法将 0.5 存储在 int 中。

在 Haskell 代码中,所有变量都是双精度(或者更确切地说是小数),因此您应该在 C 版本中执行相同操作,并将所有变量和参数声明为 double

【讨论】:

  • 我认为参数应该保留为ints,否则无法与01 进行比较。
  • @AntonSavin 它们在 Haskell 中是双打的,所以为了等价,它们在 C 中也应该是双打。此外,除非我遗漏了什么,否则对参数所做的任何操作都不会使与 1 和 0 的比较不准确。
猜你喜欢
  • 2021-12-20
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 2019-07-03
  • 1970-01-01
相关资源
最近更新 更多