Я пытаюсь понять этот код:
r = (1:10) - (4/1)
println(r)
Выход:
-3.0:1.0:6.0
Я понял, почему у меня есть -3
и 6
. Но почему я получил это значение посередине (1.0)? Как Юля рассчитывает? Или как мне это погуглить?
Я пытаюсь понять этот код:
r = (1:10) - (4/1)
println(r)
Выход:
-3.0:1.0:6.0
Я понял, почему у меня есть -3
и 6
. Но почему я получил это значение посередине (1.0)? Как Юля рассчитывает? Или как мне это погуглить?
Синтаксис (first:step:last)
представляет тип Range
в Джулии
typeof(1:10) # => UnitRange{Int32}
Если часть шага опущена, по умолчанию предполагается 1
1:10 == 1:1:10 # => true
Range
- это компактный вид серии
collect(1:10) # => 10-element Array{Int32,1}:
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
# 10
Таким образом, ожидается, что тип Range
и тип Vector
следуют одним и тем же правилам, например, когда вы добавляете постоянное значение, подобное этому:
collect(1+(1:10))==collect(1:10)+1 # => true
или даже добавление двух векторов даст вам тот же результат, что и добавление их представления диапазона следующим образом:
collect((1:10)+(1:10))==collect(1:10)+collect(1:10) # => true
1:10 === 1:1:10
, только то, что 1:10 == 1:1:10
. Первый - UnitRange
, а второй - StepRange
. Также было бы неплохо упомянуть, что isa(1:10,AbstractVector) # => true
.
- person Andreas Noack; 22.10.2015
1:10 !== 1:1:10
действительно была опечатка, я редактирую это. сейчас 1:10 == 1:1:10 # => true
- person Reza Afzalan; 22.10.2015
Оператор деления в 4/1
возвращает Float64
. Хотя первоначальный диапазон представляет собой диапазон размера 1 с шагом Int
, после добавления плавающей запятой к обеим сторонам он становится диапазоном Float64
. Таким образом, размер шага 1,0 создается путем преобразования неявного целочисленного размера шага (числа с плавающей запятой распределяются неравномерно, поэтому равномерное пошаговое выполнение немного сложнее — иногда возникают проблемы с округлением).
Вы можете увидеть это, применяя float
к интервалу:
julia> 1:10
1:10
julia> float(1:10)
1.0:1.0:10.0
и это продвижение необходимо перед добавлением в Float64 4/1
(4.0
).
Точно так же при добавлении целого числа к веществу с плавающей запятой julia «превращает» число в число с плавающей запятой перед добавлением/вычитанием:
julia> 1 + 2.0
3.0
julia> @which 1 + 2.0
+(x::Number, y::Number) at promotion.jl:172
см. правила продвижения:
+(x::Number, y::Number) = +(promote(x,y)...)
Вы можете @which
проследить все вызовы функций, чтобы понять, что происходит (вплоть до следующее):
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))
и, следовательно, продвижение-добавление Int64 и Float64.
Обратите внимание, что в мастере отображение интервала немного менее запутанно/двусмысленно:
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