简体   繁体   English

Julia中的任意精度算术

[英]Arbitrary Precision Arithmetic in Julia

This has kinda been asked, but not in this way. 有人问过这个问题,但不是这样。 I have a little Python program which finds continued fractions for square roots of n (1 <= n <= 10000). 我有一个小的Python程序,可以找到n的平方根的连续分数(1 <= n <= 10000)。

I have been trying to do this in Julia and I can't see how to. 我一直在尝试在Julia中执行此操作,但看不到该怎么做。 Mainly because it deals with irrational numbers (sqrt(x) is irrational if x is not a perfect square, eg sqrt(2) = 1.414213...). 主要是因为它处理无理数(如果x不是理想的平方,sqrt(x)是无理的,例如sqrt(2)= 1.414213 ...)。 So I don't think I can use the rational class. 所以我认为我不能使用理性类。

It says here https://docs.julialang.org/en/latest/manual/integers-and-floating-point-numbers/#Arbitrary-Precision-Arithmetic-1 that Julia can do arbitrary precision arithmetic with BigFloats. 它在这里https://docs.julialang.org/en/latest/manual/integers-and-floating-point-numbers/#Arbitrary-Precision-Arithmetic-1表示Julia可以使用BigFloats进行任意精度算术。 But they don't seem to be accurate enough. 但是它们似乎不够准确。

I have also tried to use PyCall and the Decimals package in Python (from Julia), but get weird errors (I can post them if they would be helpful). 我也曾尝试在Python中使用PyCall和Decimals软件包(来自Julia),但出现了奇怪的错误(如果它们会有所帮助,我可以将其发布)。

Here is my Python program which works. 这是我的Python程序。 And my question is how to do this in Julia please? 我的问题是如何在朱莉娅中做到这一点?

def continuedFractionSquareRoots():
''' 
  For each number up to 100, get the length of the continued fraction 
  of the square root for it.
'''

decimal.getcontext().prec = 210 # Need lots of precision for this problem.

continuedFractionLengths = []
for i in range(1, 101):

    # For perfect squares, the period is 0
    irrationalNumber = decimal.Decimal(i).sqrt()
    if irrationalNumber == int(irrationalNumber):
        continue        

    continuedFractionLength = 0
    while True:

        intPart = irrationalNumber.to_integral_exact(rounding=decimal.ROUND_FLOOR)
        if continuedFractionLength == 0:
            firstContinuedFractionTimes2 = int(intPart*2)

        continuedFractionLength += 1
        if intPart == firstContinuedFractionTimes2:
            # Have reached the 'period' end for this fraction
            break

        fractionalPart = irrationalNumber - intPart
        irrationalNumber = 1 / fractionalPart

continuedFractionLengths.append(continuedFractionLength)
return continuedFractionLengths

So as you can see, I need a way of computing an exact square root and also a way to get the integer part of the number. 如您所见,我需要一种计算确切平方根的方法,还需要一种获取数字的整数部分的方法。 And that's all really, apart from lots and lots of precision! 真的,除了很多又很多的精度之外!

Guys, I didn't post my Julia code because I didn't want to have a small manuscript for an answer! 伙计们,我没有张贴我的Julia代码,因为我不想写一个小的手稿作为答案! But here it is, it works. 但是在这里,它是可行的。 As I said in the comments below, I used the setprecision function to set the precision to a high value and it works. 正如我在下面的评论中所说,我使用setprecision函数将精度设置为较高的值,并且可以正常工作。 I got the value 711 empirically. 我凭经验得到值711。

setprecision(711)

function continuedFractionSquareRoots()
#=
  For each number up to 100, get the length of the continued fraction 
  of the square root for it.
=#

continuedFractionLengths = Int[]
for i=1:100

    # For perfect squares, the period is 0
    irrationalNumber = BigFloat(sqrt(BigFloat(i)))
    if irrationalNumber == floor(irrationalNumber)
        continue
    end

    continuedFractionLength = 0
    while true

        intPart = floor(irrationalNumber)
        if continuedFractionLength == 0
            firstContinuedFractionTimes2 = intPart*2
        end

        continuedFractionLength += 1
        if intPart == firstContinuedFractionTimes2
            # Have reached the 'period' end for this fraction
            break
        end

        fractionalPart = irrationalNumber - intPart
        irrationalNumber = BigFloat(1) / fractionalPart

    end

    push!(continuedFractionLengths, continuedFractionLength)

end


return continuedFractionLengths
end

So anyway, user2357112 solved it, thanks very much. 因此,无论如何,user2357112解决了它,非常感谢。

Just like with Python's decimal.Decimal, you can configure the precision of Julia's BigFloat: 就像Python的十进制十进制一样,您可以配置Julia的BigFloat的精度:

setprecision(however_many_bits)

Note that this is in bits, unlike decimal.Decimal, because BigFloat doesn't use decimal. 请注意,这是以位为单位的,这与十进制十进制不同,因为BigFloat不使用十进制。

user2357112's answer is at the heart of the problem and the correct answer to this question. user2357112的答案是问题的核心,也是此问题的正确答案。

However, for the sake of completion, the 'literal' question of "how would I get this python script to run in julia" is an interesting question in itself, as it is not as straightforward as it might first seem due to this issue , so I'll show how to do this as well. 但是,为了完整起见,“字面意义上的”问题“我如何让这个python脚本在julia中运行”本身就是一个有趣的问题,因为它并不像由于该问题而最初看起来那样简单,因此,我还将展示如何执行此操作。

Assuming you have your python script called "testo.py" in your current directory (and with the correct import decimal statements etc), then here's how to import it as a python module and run the relevant function: 假设您在当前目录中有一个名为“ testo.py”的python脚本(并带有正确的import decimal语句等),那么以下是将其作为python模块导入并运行相关功能的方法:

using PyCall
unshift!(PyVector(pyimport("sys")["path"]), ""); # as per https://github.com/JuliaPy/PyCall.jl#troubleshooting
testo = pyimport("testo");
testo[:oddPeriodSquareRoots]()  # will output '1322'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM