这可能看起来像一个奇怪的问题,但是我如何创建一个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的每个元素。我该如何实现呢?
此外,在尝试创建此类功能时可能会出现什么问题?
答案 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的解决方案。