pat*_*_ai 16 r constants function
一个R函数传递给我,它在Real Line的某个区间定义并返回一个数值.有没有办法检查功能是否恒定?
示例功能:
f1<-function(x) {11}
f2<-function(x) {x+2}
f3<-function(x) {1+1}
f4<-function(x) {return(3)}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个测试,它会说f1,f3,f4是常数函数,但f2不是.有任何想法吗?
编辑:
弗兰克和格雷戈尔(编辑:和迈克尔劳伦斯的第二个解决方案)以下解决方案都适用于上面给出的所有4个测试用例(Marat和迈克尔不对所有4个案例都有效).所以已有解决方案.但是,如果您能找到一个解决方案,并为以下3个测试功能提供正确的答案,那么额外的奖励积分:
f5 <- function(x) ifelse(x == 5.46512616432116, 0, 1)
f6 <- function(x) ifelse(x == 5.46512616432116, 0, 0)
f7 <- function(x) {x - x}
Run Code Online (Sandbox Code Playgroud)
Mar*_*pov 11
试试functionBody
:
> is.numeric(functionBody(f1)[[2]])
[1] TRUE
> is.numeric(functionBody(f2)[[2]])
[1] FALSE
Run Code Online (Sandbox Code Playgroud)
此函数测试参数f
是否用作数字:
is_using_argasnumber <- function(f)
grepl("non-numeric argument",try(f("Hello World!"),silent=TRUE))
Run Code Online (Sandbox Code Playgroud)
例子:
is_using_argasnumber(function(x)1+1) # FALSE
is_using_argasnumber(function(x)"guffaw") # FALSE
is_using_argasnumber(function(x)sqrt(x+2)) # TRUE
Run Code Online (Sandbox Code Playgroud)
如果你需要测试数学函数是否是常数,你需要特殊的工具来理解并简化公式.
概论.
"(non-numeric argument)|(argument non numérique)"
.不幸的是,据我所知,R不使用或公开"错误代码",这将允许语言不变的解释try
结果..
is_breaking_withargascharacter <- function(f)
inherits(try(f("Hello World!"),silent=TRUE),'try-error')
Run Code Online (Sandbox Code Playgroud)
这些基于代码的测试很聪明,很有趣,但到目前为止,我认为"尝试一堆数字"的方法可能是一个更强大的测试,取决于你可能获得的函数类型以及你是否更关心Type I或您的身份证明中的II型错误.
在你的问题中,你说
它是在Real Line的某个区间定义的
所以我们假设我们知道感兴趣的领域.在该域上采样一些点,并测试您的功能.
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
Run Code Online (Sandbox Code Playgroud)
任何真正是常数函数的函数都会通过这个测试,无论多么病态 - 对于目前为止建议的任何其他方法都不会这样.但是,使用我在评论中留下的示例(或任何此类内容)来愚弄测试很容易
f3 = function(x) ifelse(x == 5.46512616432116, 0, 1)
Run Code Online (Sandbox Code Playgroud)
这可以处理显式return
,缺失{
甚至空的情况{ }
:
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))
Run Code Online (Sandbox Code Playgroud)
这是另一种非常聪明的方法,但它可以被欺骗.假设给定常量参数,它将假定任何原始函数将返回相同的值.只要符号在函数内定义,它也允许使用符号.但由于符号可以在定义之前引用,也可以在嵌套范围内定义,因此启发式不安全.无论如何,这里是:
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)))
}
Run Code Online (Sandbox Code Playgroud)
应该是TRUE
:
evaluatesToConstant(functionBody(function(x) { foo <- 1 + 1; foo }), TRUE)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
890 次 |
最近记录: |