C ++函数判断给定函数是否是单射的

时间:2014-03-25 18:09:31

标签: c++

这可能看起来像一个奇怪的问题,但是我如何创建一个C ++函数来告诉一个给定的C ++函数是否将一个X类型的变量作为参数并返回一个X类型的变量,这个函数是空的。那些变量的机器表示,即永远不会为传递给它的两个不同变量返回相同的变量?

(对于那些不是数学专业的人,如果你仍然对内射的定义感到困惑,可以看看这个页面:http://en.wikipedia.org/wiki/Injective_function

例如,函数

double square(double x) { return x*x}; 
由于square(2.0) = square(-2.0)

不是单射的

但功能

double cube(double x) { return x*x*x};
显然是

目标是创建一个功能

 template <typename T>
 bool is_injective(T(*foo)(T))
 {
    /* Create a set std::set<T> retVals;
       For each element x of type T: 
       if x is in retVals, return false;
       if x is not in retVals, add it to retVals;
       Return true if we made it through the above loop.
    */
 }

我想我可以实现那个程序,除了我不知道如何遍历类型T的每个元素。我该如何实现呢?

此外,在尝试创建此类功能时可能会出现什么问题?

4 个答案:

答案 0 :(得分:2)

您需要测试每个可能的长度为sizeof(T)的位模式。

最近有一篇关于这个主题的博文广为流传:There are Only Four Billion Floats - So Test Them All!

在该帖子中,作者能够在90秒内测试所有32位浮点数。事实证明,对于64位值,需要几个世纪的时间。

所以这只适用于小输入类型。

多个输入,结构或带指针的任何东西都会变得不可能快。

顺便说一句,即使使用32位值,您可能会耗尽系统内存,试图将所有输出值存储在std::set中,因为std::set会为指针使用大量额外内存。相反,您应该使用足以容纳所有2^sizeof(T)输出值的位图。专门的std::vector<bool>应该有效。这需要2^sizeof(T) / 8字节的内存。

答案 1 :(得分:1)

也许你需要的是std::numeric_limits。要存储结果,您可以使用unordered_map(如果您使用的是C ++ 11,则来自std,如果不是,则来自boost。)

您可以检查数据类型的限制,也许类似可能的工作(这是一个愚蠢的解决方案,但它可能会让您入门):

template <typename T>
bool is_injective(T(*foo)(T))
{
    std::unordered_map<T, T> hash_table;

    T min = std::numeric_limits<T>::min();
    T max = std::numeric_limits<T>::max();

    for(T it = min; i < max; ++i)
    {
        auto result = hash_table.emplace(it, foo(it));
        if(result.second == false)
        {
            return false;
        }
    }

    return true;
}

当然,您可能希望限制一些可能的数据类型。否则,如果检查浮点数,双精度数或长整数,它将变得非常密集。

答案 2 :(得分:1)

  

但功能

   double cube(double x) { return x*x*x};
     显然是

显然不是。 [0..0.5]中有2 ^ 53个double值可以在[0..0.125]中表示。

答案 3 :(得分:0)

据我所知,你不能在C ++中迭代所有可能的类型值。

但是,即使你可以,这种方法也无处可寻。如果您的类型是64位整数,则可能必须迭代2 ^ 64个值并跟踪所有这些值的结果,这是不可能的。

与其他人说的一样,没有通用类型X的解决方案。