Что нового

[Математика] Фукнция разбивки числа на слагаемые степени двойки

Rioran

Everything is possible and achievable.
Сообщения
26
Репутация
2
AutoIt: Тестировалось на 3.3.12.0
Версия: 1.00

Категория: Вспомогательные функции, Строки, Математика.

Описание: Функция раскладывает целое положительное число на слагаемые степени двойки и возвращает строку, где множители разбиты через символ "+". Можно использовать в комбинации со StringSplit по символу "+" для получения массива слагаемых. Алгоритм рекомендуется использовать максимум на 14-значных числах ввиду ограничения на возведение в степень. При желании можно доработать пользовательской функцией, как это сделано ЗДЕСЬ. Может замедлить скорость работы.

Код/Пример:
Код:
Global $nNumber = 32767 ; Какое число разбиваем на слагаемые степени двойки
ConsoleWrite($nNumber & " = " & GetCompositionNumbers($nNumber) & @CRLF)

func GetCompositionNumbers($nVal)
; Автор: Роман "Rioran" Воронов
; Версия: 1-00 от 17.09.2015
; ---------------------------
; Программа предназначена для получения слагаемых степеней двойки
; Function returns composition numbers of a given value
   Local $sText, $X, $Power = 0
   While $nVal >= 1
	  If IsInt($nVal/2) Then
		 $X = 0
	  Else
		 $nVal = $nVal - 1
		 $X = 1
	  EndIf
	  $nVal /= 2
	  If $X Then $sText = $sText & "+" & (2 ^ $Power)
	  $Power += 1
   WEnd
   return StringMid($sText, 2)
EndFunc


История версий:
1.00: первая публичная версия

Автор: Роман "Rioran" Воронов
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Это я давно делал для CaptureText, проверить наличие кратных двойке или логическихTrue/False в двоичной системе. для указанного числа. Или разложение числа-стиля на составляющие.
Код:
Func _ArrGetVal($Value)
	If $Value = 0 Then Return
	Local $sOut, $n = 0.5
	For $i = 0 To Int(Log($Value) / Log(2))
		$n *= 2
		If BitAND($Value, $n) Then $sOut &= '0x' & Hex(Int($n), 8) & @LF
		; If BitAnd($Value, $n) Then $sOut&='0x'&StringFormat("%08x", $n) &@LF
		; If BitAnd($Value, $n) Then $sOut&=StringFormat("%#x", $n) &@LF
	Next
	Return StringTrimRight($sOut, 1)
EndFunc   ;==>_ArrGetVal
 
Автор
Rioran

Rioran

Everything is possible and achievable.
Сообщения
26
Репутация
2
AZJIO, спасибо за интересный вариант. Я восхищён красотой решения. Я сравнил со своей функцией и вот что обнаружил.

- Твоя функция работает немного быстрее. Я несколько раз провёл по 100 тысяч вычислений для числа 32767. Моя функция в среднем решала за 6.8 секунд, а твоя за 6.6 секунд.
- Твоя функция возвращает числа в 32-битном формате (определяется использованием оператора BitAND), что накладывает ограничения. Начиная с числа 4294967296 (2^32) и до 2^50 я бы рекомендовал использовать мою функцию, т.к. твоя функция принимает 4294967296 за ноль, 4294967297 за 1 и так далее.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Rioran [?]
Твоя функция возвращает числа в 32-битном формате (определяется использованием оператора BitAND)
BitAND не используется в возвращении, а только в проверке наличия.
Цикл For я использовал чтобы не проверять когда достигнут предел и не подготавливать переменную делением на 2 внутри цикла чтобы с ней потом сравнивать.
А в 16-ричном формате возвращается за счёт функции Hex, то есть если её убрать будет и нужный формат и прибавка к скорости.
что накладывает ограничения. Начиная с числа 4294967296 (2^32) и до 2^50 я бы рекомендовал использовать мою функцию, т.к. твоя функция принимает 4294967296 за ноль, 4294967297 за 1 и так далее.
Вообще AutoIt работает с некоторым ограничением по длине числа и работа с числами на краях диапазона каждый раз индивидуально, например возвести число в к куб быстрее столкнутся чем сложение числа с единицей, так как в последнем случае число будет практически на границе диапазона, а в первом случае далеко до. Но с практической стороны это используется для разложения стилей, а их длина как раз ограничивается возможностью работы моей функции
 
Верх