2015-10-21 12 views
8

Próbuję zrozumieć ten kod:(x: y) operator Julia

r = (1:10) - (4/1) 
    println(r) 

wyjściowa:

-3,0: 1,0: 6,0

zrozumiałem, dlaczego ja otrzymał -3 i 6. Ale dlaczego mam tę wartość w środku (1.0)? Jak Julia to oblicza? Lub jak mogę google to?

Odpowiedz

12

(first:step:last) składnia reprezentują typ Range w Julia

typeof(1:10) # => UnitRange{Int32} 

Jeśli część krok zostanie pominięty, domyślnie przyjmuje się 1

1:10 == 1:1:10 # => true 

Range to kompaktowy widok serii

collect(1:10) # => 10-element Array{Int32,1}: 
# 1 
# 2 
# 3 
# 4 
# 5 
# 6 
# 7 
# 8 
# 9 
# 10 

Tak więc można się spodziewać ed że Range typ i Vector wykonaj te same zasady, na przykład podczas dodawania stałą wartość takiego:

collect(1+(1:10))==collect(1:10)+1 # => true 

lub nawet dodanie dwóch wektorów daje ten sam wynik dodawania ich reprezentacji zakres tak:

collect((1:10)+(1:10))==collect(1:10)+collect(1:10) # => true 
+0

dobre wytłumaczenie, dzięki! –

+1

To prawdopodobnie tylko literówka, ale nie jest prawdą, że '1:10 === 1: 1: 10', tylko że' 1:10 == 1: 1: 10'. Pierwszy to "UnitRange", a drugi to "StepRange". Warto również wspomnieć, że 'isa (1: 10, AbstractVector) # => true'. –

+0

Dzięki @Andreas za komentarz na temat "1:10! == 1: 1: 10" naprawdę to był literówka, edytuję to. teraz '1:10 == 1: 1: 10 # => prawda' –

3

Operator podziału w 4/1 zwraca Float64. Chociaż pierwotny zakres to rozmiar 1 Int, po dodaniu punktu zmiennoprzecinkowego na obie strony staje się zasięgiem z zakresu Float64. W związku z tym, rozmiar kroku 1.0 jest tworzony przez konwersję niejawnego rozmiaru liczby całkowitej (liczby zmiennoprzecinkowe są nierównomiernie rozłożone, więc jednolite kroczenie jest trochę trudne - czasami występują problemy z zaokrąglaniem).

2

Widać to przy stosowaniu float do przedziału:

julia> 1:10 
1:10 

julia> float(1:10) 
1.0:1.0:10.0 

a ta promocja jest wymagane przed dodaniem do Float64 4/1 (4.0).

Podobnie, podczas dodawania liczbę całkowitą do Julia pływaka "promuje" liczbę całkowitą do pływaka przed dodanie/odjęcie:

julia> 1 + 2.0 
3.0 

julia> @which 1 + 2.0 
+(x::Number, y::Number) at promotion.jl:172 

zobaczyć the promotion rules:

+(x::Number, y::Number) = +(promote(x,y)...) 

Można @which wykonaj funkcję połączenia od końca do końca, aby zrozumieć, co się dzieje (aż do the following):

julia> @which +(1:10, 2.0) 
+(A::AbstractArray{T,N}, x::Number) at arraymath.jl 

julia> @which .+(1:10, 2.0) 
.+(r::Range{T}, x::Real) at range.jl 

julia> @which .+(2.0, 1:10) 
.+(x::Real, r::UnitRange{T<:Real}) at range.jl 

# which is defined as 
.+(x::Real, r::UnitRange) = range(x + r.start, length(r)) 

i tym samym promocja-dodanie Int64 i Float64.


Uwaga master wyświetlacz interwału jest nieco mniej kłopotliwe/dwuznaczny:

julia> float(1:10) 
10-element FloatRange{Float64}: 
1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 

julia> 1:10 
10-element UnitRange{Int64}: 
1,2,3,4,5,6,7,8,9,10 
Powiązane problemy