Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何检查R中的函数是否为常数函数?_R_Function_Constants - Fatal编程技术网

如何检查R中的函数是否为常数函数?

如何检查R中的函数是否为常数函数?,r,function,constants,R,Function,Constants,一个R函数被传递给我,它在实数行的某个间隔上定义并返回一个数值。 有没有办法检查函数是否为常数 示例功能: f1<-function(x) {11} f2<-function(x) {x+2} f3<-function(x) {1+1} f4<-function(x) {return(3)} f5 <- function(x) ifelse(x == 5.46512616432116, 0, 1) f6 <- function(x) ifelse(x ==

一个R函数被传递给我,它在实数行的某个间隔上定义并返回一个数值。 有没有办法检查函数是否为常数

示例功能:

f1<-function(x) {11}
f2<-function(x) {x+2}
f3<-function(x) {1+1}
f4<-function(x) {return(3)}
f5 <- function(x) ifelse(x == 5.46512616432116, 0, 1)
f6 <- function(x) ifelse(x == 5.46512616432116, 0, 0)
f7 <- function(x) {x - x}

f1尝试
functionBody

> is.numeric(functionBody(f1)[[2]])
[1] TRUE

> is.numeric(functionBody(f2)[[2]])
[1] FALSE

此函数测试
f
的参数是否用作数字:

is_using_argasnumber <- function(f) 
  grepl("non-numeric argument",try(f("Hello World!"),silent=TRUE))
如果你需要测试一个数学函数是否为常数,你需要能够理解并简化公式的特殊工具


通用性。

  • 这在具有多个参数的函数上没有意义
  • 如果使用不同的R本地化。。。
    • 我建议替换或添加正则表达式,例如,使用
      (非数值参数)|(非数值参数)
      。不幸的是,据我所知,R并没有使用或公开允许对
      try
      结果进行语言不变解释的“错误代码”
    • OP提出的另一种选择是简单地检查是否存在任何错误,但我认为如果被测试的功能有任何可能出现错误,就会产生太多的误报:


正在突破argascharacter这些基于代码的测试既聪明又有趣,但到目前为止,我认为“尝试一堆数字”方法可能是一种更强大的测试,这取决于您可能获得的函数类型,以及您是否更关心标识中的I型或II型错误

在你的问题中,你说

定义在实线的某个区间上

假设我们知道感兴趣的领域。在该域上采样一些点,并测试您的功能

n = 1e5
test = runif(n, min = 0, max = 5)
results = f(test) # sapply(test, f) if f isn't vectorized

# test for constancy
all(results == results[1]) # or all(diff(results) == 0) or however else
任何真正是常量函数的函数都可以通过这个测试,不管它有多病态——这对于目前为止提出的任何其他方法都是不正确的。然而,用我在评论中留下的例子(或任何类似的例子)来愚弄测试是很容易的


如果您假装该函数是其“mathworld”对应函数,则问题的答案是递归不可判定的。

这将处理显式
返回
、缺少
{
甚至为空
{}

evaluatesToConstant <- function(b) {
    if (is(b, "{")) {
        if (length(b) > 2L)
            return(FALSE)
        if (length(b) == 1L)
            last <- NULL
        else last <- b[[2L]]
    } else {
        last <- b
    }
    if (is.call(last) && last[[1L]] == quote(return)) {
        last <- last[[2L]]
    }
    !is.language(last)
}
evaluatesToConstant(functionBody(fun))


你能做的最好的事情就是尝试一组值。祝你好运抓住我的函数
f3=函数(x)ifelse(x==5.46512616432116,0,1)
。不确定是否可以通过编程实现任意函数。但如果你能说出上下文,也许有人能提出解决方案。没错,Gregor,我希望能够捕获这样的函数。这就是为什么我希望有一个编程解决方案,而不是测试一组值。因为R知道函数信息理论上是存在的…但是如果你的域是0到5,我的函数是一个常量函数。为了解决这个合理的问题,我认为你需要能够做出更有力的假设。这些函数是如何创建的?你有固定的域吗?函数有多复杂,它们可能调用其他函数?我还可以编写一个非常迟钝的函数,它看起来非常复杂,但总是常量。如果您想测试代码是否使用
x
作为数字,只需传递一个非数字,然后享受错误:
f1(“a”);f2(“a”)
。这不会捕捉到恒常性是数学的,而不是编程的情况,就像Gregor所说的,
f3谢谢!!它不是傻瓜式的,例如f4=function(x)ifelse(x==5.46512616432116,0,0)虽然它不是常量,但它足够接近了。@bisounours\u tronconneuse-因为从技术上讲,这是一个函数调用,而不是常量。它取决于另一个变量:)@bisounours\u tronconneuse,试试
f3您可能可以在Marat的答案中添加
eval
,以确保进行求值,因为1+1也是一个变量函数调用.Like
is.numeric(eval(functionBody(f3)[[2]])
一旦有函数调用,所有的赌注都是无效的。这个答案的一个容易解决的问题是,它需要对没有
{
的情况保持健壮。更好的检查方法是
!is.language()
而不是
is.numeric())
。谢谢!这很好,但只有当您的系统语言为英语时它才能工作;)例如,我得到:try(f2(“Hello World!”)x+2中的错误:参数非数值二值化如果将解决方案修改为只捕获错误会更好。@bisounours\u tronconneuse是的,我同意。我不习惯捕获错误,所以我现在正在研究如何修改它。但是,知道我们捕获了正确的错误是很好的……就像捕获错误一样或者代码,假设R有这些。比如说,is_使用_argasnumber,我仍然不确定OP是在寻找函数属性还是数学属性测试,但我喜欢后者的解决方案,至少是“我如何测试我的实值函数是否从实值的紧凑子集中是常数?”而且,如果函数不是以某种方式“随机”生成的,那么也很容易检查“特殊”值,如果它包含在域中,则为0,可能会检查
pretty(mydomain)
中的值。我尝试了你的函数,但问题中的f2失败。该函数为true,而它应该为false……>evaluatesToConstant(f2)[1]真>f2函数(x){x+2}对不起,我的错,我没有意识到我应该做evaluatesToConstant(函数体(乐趣))不仅仅是evaluatesToConstant。是的,因为要支持像
+
这样的东西,需要将总是返回相同结果的函数调用列为白名单,给定常量参数。我想这可能适用于任何原语。我将为答案添加不同的方法。
n = 1e5
test = runif(n, min = 0, max = 5)
results = f(test) # sapply(test, f) if f isn't vectorized

# test for constancy
all(results == results[1]) # or all(diff(results) == 0) or however else
f3 = function(x) ifelse(x == 5.46512616432116, 0, 1)
evaluatesToConstant <- function(b) {
    if (is(b, "{")) {
        if (length(b) > 2L)
            return(FALSE)
        if (length(b) == 1L)
            last <- NULL
        else last <- b[[2L]]
    } else {
        last <- b
    }
    if (is.call(last) && last[[1L]] == quote(return)) {
        last <- last[[2L]]
    }
    !is.language(last)
}
evaluatesToConstant(functionBody(fun))
evaluatesToConstant <- function(expr, allowDefinitions=FALSE) {
    vars <- all.vars(expr)
    calls <- setdiff(all.names(expr), vars)
    funs <- mget(calls, parent.frame(), mode="function", inherits=TRUE)
    defined <- if (allowDefinitions)
                   rapply(as.list(expr),
                          function(x) as.character(substitute(x)[[2L]]), "<-",
                          how="unlist")
    length(setdiff(vars, defined)) == 0L &&
        all(vapply(funs, is.primitive, logical(1L)))
}
evaluatesToConstant(functionBody(function(x) { foo <- 1 + 1; foo }), TRUE)