朱莉娅@evalpoly宏与varargs [英] Julia @evalpoly macro with varargs

查看:96
本文介绍了朱莉娅@evalpoly宏与varargs的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Julia的@evalpoly宏.当我手动提供系数时,它可以工作,但我一直无法解开如何通过数组提供这些系数

I'm trying to grok using Julia's @evalpoly macro. It works when I supply the coefficients manually, but I've been unable to puzzle out how to provide these via an array

julia> VERSION
v"0.3.5"

julia> @evalpoly 0.5 1 2 3 4
3.25

julia> c = [1, 2, 3, 4]
4-element Array{Int64,1}: 
 1
 2
 3
 4

julia> @evalpoly 0.5 c
ERROR: BoundsError()

julia> @evalpoly 0.5 c...
ERROR: BoundsError()

julia> @evalpoly(0.5, c...)
ERROR: BoundsError()

有人可以为此指出正确的方向吗?

Can someone point me in the right direction on this?

在看到这个问题的好答案后添加

直到我回答了其中一些答案之后,我才发现其中的一个微妙之处. @evalpolyz参数可以是变量,但系数应为文字量

There is one subtlety to that I hadn't seen until I played with some of these answers. The z argument to @evalpoly can be a variable, but the coefficients are expected to be literals

julia> z = 0.5
0.5

julia> @evalpoly z 1 2 3 4
3.25

julia> @evalpoly z c[1] c[2] c[3] c[4]
ERROR: c not defined

查看最后一条命令的扩展输出,可以看到确实是在扩展中将z分配给变量的情况,但实际上是在代码中插入了系数.

Looking at the output of the expansion of this last command, one can see that it is indeed the case that z is assigned to a variable in the expansion but that the coefficients are inserted literally into the code.

julia> macroexpand(:@evalpoly z c[1] c[2] c[3] c[4])
:(if Base.Math.isa(z,Base.Math.Complex)
        #291#t = z
        #292#x = Base.Math.real(#291#t)
        #293#y = Base.Math.imag(#291#t)
        #294#r = Base.Math.+(#292#x,#292#x)
        #295#s = Base.Math.+(Base.Math.*(#292#x,#292#x),Base.Math.*(#293#y,#293#y))
        #296#a2 = c[4]
        #297#a1 = Base.Math.+(c[3],Base.Math.*(#294#r,#296#a2))
        #298#a0 = Base.Math.+(Base.Math.-(c[2],Base.Math.*(#295#s,#296#a2)),Base.Math.*(#294#r,#297#a1))
        Base.Math.+(Base.Math.*(#298#a0,#291#t),Base.Math.-(c[1],Base.Math.*(#295#s,#297#a1)))
    else 
        #299#t = z
        Base.Math.+(Base.Math.c[1],Base.Math.*(#299#t,Base.Math.+(Base.Math.c[2],Base.Math.*(#299#t,Base.Math.+(Base.Math.c[3],Base.Math.*(#299#t,Base.Math.c[4]))))))
    end)

推荐答案

我不相信您尝试做的事情是可能的,因为@evalpoly是宏-这意味着它在编译时生成代码.它生成的是霍纳方法的一个非常有效的实现(在实数情况下),但是要做到这一点,它需要知道多项式的阶数. c的长度在编译时未知,因此它不起作用(也不能),而直接提供系数时,它具有所需的一切.

I don't believe what you are trying to do is possible, because @evalpoly is a macro - that means it generates code at compile-time. What it is generating is a very efficient implementation of Horner's method (in the real number case), but to do so it needs to know the degree of the polynomial. The length of c isn't known at compile time, so it doesn't (and cannot) work, whereas when you provide the coefficients directly it has everything it needs.

错误消息不是很好,所以如果可以,您可以在Julia Github页面上提交问题吗?

The error message isn't very good though, so if you can, you could file an issue on the Julia Github page?

UPDATE:是的,响应问题的更新,是的,第一个参数可以是变量.您可以这样想:

UPDATE: In response to the update to the question, yes, the first argument can be a variable. You can think of it like this:

function dostuff()
  z = 0.0
  # Do some stuff to z
  # Time to evaluate a polynomial!
  y = @evalpoly z 1 2 3 4
  return y
end

正在成为

function dostuff()
  z = 0.0
  # Do some stuff to z
  # Time to evaluate a polynomial!
  y = z + 2z^2 + 3z^3 + 4z^4
  return y
end

除外,并非如此,因为它使用了霍纳斯规则,但无论如何.问题是,如果不知道系数的数量,就无法在编译时生成该表达式.但这根本不需要知道z是什么.

except, not that, because its using Horners rule, but whatever. The problem is, it can't generate that expression at compile time without knowing the number of coefficients. But it doesn't need to know what z is at all.

这篇关于朱莉娅@evalpoly宏与varargs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆