Добавлен scopterectus
Мне нужно преобразовать real в integer так, чтобы каждый real имел свой integer (как у функции GetHandleId( ), только вместо handle должен быть real). Нативная функция R2I( ) может вернуть одно и то же значение для разных real'ов ( R2I( 0.01 ) == R2I( 0.02 ) ).
Попробовал умножать real на 10 000 000, так, например, GetRealId( 0.03125 ) == 312500, но так можно упереться в потолок 2147483647
function GetRealId takes real whichReal returns integer
return ( whichReal * 10000000 )
endfunction
В мемхаке нашел следующую функцию, но хотелось бы, чтобы функция работала без return bug'a
раскрыть
//# +nosemanticerror
function realToIndex takes real r returns integer
loop
return r
endloop
return 0
endfunction
function cleanInt takes integer i returns integer
return i
endfunction
function mR2I takes real r returns integer
return cleanInt( realToIndex( r ) )
endfunction
Можно сократить до (вроде работает):
//# +nosemanticerror
function R2IEx takes real r returns integer
loop
return r
endloop
return 0
endfunction
Принятый ответ
Сделал следующим образом:
раскрыть
function interface callback takes integer this returns nothing defaults nothing
struct linkedList
private static timer period = null
private real curTimeout
private real timeout
private thistype prev
private thistype next
private callback handlerFunc
static constant method operator listPeriod takes nothing returns real
return 0.01
endmethod
method destroy takes nothing returns nothing
set this.prev.next = this.next
set this.next.prev = this.prev
if (thistype(0).next == thistype(0)) then
call PauseTimer(this.period)
endif
call thistype.deallocate(this)
endmethod
private static method iterate takes nothing returns nothing
local thistype this = thistype(0).next
loop
exitwhen (this == thistype(0))
set this.curTimeout = this.curTimeout + thistype.listPeriod
if (this.curTimeout >= this.timeout) then
set this.curTimeout = 0.0
call this.handlerFunc.evaluate(integer(this))
endif
set this = this.next
endloop
endmethod
static method create takes real timeout, callback handlerFunc returns thistype
local thistype this = thistype.allocate()
set this.next = thistype(0)
set this.prev = thistype(0).prev
set this.next.prev = this
set this.prev.next = this
set this.timeout = timeout
set this.curTimeout = 0.0
set this.handlerFunc = handlerFunc
if (thistype.period == null) then
set thistype.period = CreateTimerEx()
endif
if (this.prev == thistype(0)) then
call TimerStart(thistype.period, thistype.listPeriod, true, function thistype.iterate)
endif
return this
endmethod
endstruct
Будет ли это создавать большую нагрузку на игру из-за низкого периода таймера, несмотря на то, что таймер хоть и работает с низкой частотой, он ничего толком то и не делает, кроме арифметических вычислений?
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован Clamp
Отредактирован scopterectus
Я бы сказал, что мною движет желание это сделать больше, чем оптимизация кода.
Вариант со StringHash(R2S(r)) здесь будет наиболее уместным, однако помни, что строки никуда из памяти не деваются, и остаются висеть в оперативе.
call BJDebugMsg( I2S( StringHash( R2S( 0.03126 ) ) ) ) == -1331723389
Отредактирован PT153
В математике R не ограничено, но наш мир ограничен, потому число действительных чисел ограничено в программировании. Каждому целому числу сопоставлено число с плавающей точкой.
Не используй R2S, это R2SW с точностью 3. Лучше используй R2SW с точностью -1.
В целом Clamp, говорит верно, такие потребности не должны возникать в логике программы, поскольку типы с плавающей запятой ненадежны, они с потерями.
Если нужно совсем прям совсем, можно использовать vJass/ZINC/Wurst и объявить структуру (в случае Wurst - класс) который будет содержать в поле данные типа real. Что-то вроде