Что нового

[Осваивающий, Продвинутый] Конвертация чисел в разные системы счисления и обратно

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Построить две функции для конвертации чисел в другую систему счисления и обратно следующего вида
Код:
; Название функции...........: DecToN($decnum, $base)
; Описание функции ..........: Конвертация числа в заданную систему счисления
; Входные параметры..........: $decnum - десятичное целое число
; ...........................: $base - основание системы счисления (не больше 10)
; Выходные параметры.........: Строка вида  'xxnyyyyy', где
; ...........................: xx - основание системы счисления (тоже что и  $base)
; ...........................: n - символ разделяющий основание системы счисления и представление числа
; ...........................: yyyy - представление числа в системе счисления с основанием $base


; Название функции...........: NToDec($nnum)
; Описание функции ..........: Конвертация числа в десятичную систему счисления
; Входные параметры..........: $nnum - число-строка в заданной системе счисления вида 'xxnyyyy'
; Выходные параметры.........: Число в десятичном представлении
Например, число 18118 имеет следующие представления в различных системах счисления (с учетом формата в условии задачи)
Код:
+-----------+-----------------------+
| Основание | Число                 |
+-----------+-----------------------+
| 2         | '2n100011011000110'   |
| 3         | '3n220212001'         |
| 4         | '4n10123012'          |
| 5         | '5n1034433'           |
| 6         | '6n215514'            |
| 7         | '7n103552'            |
| 8         | '8n43306'             |
| 9         | '9n26761'             |
+-----------+-----------------------+
Поэтому DecToN(18118, 6), к примеру, должно давать '6n215514', а NToDec('4n10123012') должно давать 18118.

Использование каких-либо сторонних библиотек запрещено. Код заключайте в тэг спойлера.

PS: Задача ориентировочно расчитана на осваивающих и продвинутых, но при желании и возможности новички так же могут присоединиться к решению
 

Zaramot

I ♥ AutoIt
AZJIO,
Там же пишут [Осваивающий, Продвинутый] , а не Гуру :D
 

AZJIO

Меценат
Меценат
Zaramot
Я думал что я продвинутый. А то я ещё хотел уже выложить вариант до шестнадцатеричной системы.
 

C2H5OH

AutoIT Гуру
А я в AutoIt не Гуру. Мне можно. ;D

Код:
$x = 18118
$N = 6

$y = DecToN($x,$N)

ConsoleWrite("y = " & $y & @CR)

$z = NToDec($y)

ConsoleWrite("z = " & $z & @CR)


Func DecToN($decnum, $base)
	Local $res_str = ""
	If $base = 0 Then Return ""
	If $base = 1 Then					;  А вы не знали что существуед единичная система счисления??
		For $i = 1 to $decnum			;
			$res_str &= "1"				;
		Next							;
		$res_str = "1n" & $res_str		;
		Return $res_str					;
	EndIf								;
	While $decnum > 0
		$rest = Mod($decnum, $base)
		If $rest > 9 Then								; сразу как-то получилось и с основаниями больше 10
			$res_str = Chr(55 + $rest) & $res_str		;
		Else											; ну разрыв идёт в ASCII
			$res_str = Chr(48 + $rest) & $res_str		; Chr(48) == "0", Chr(57) == "9"
		EndIf											; Chr(65) == "A", ...
		$decnum = Floor($decnum/$base)
	WEnd
	If $res_str = "" Then $res_str = "0"
	$res_str = String($base) & "n" & $res_str
	Return $res_str
EndFunc

Func NToDec($nnum)
	$narray = StringSplit($nnum, "n")
	if @error Then Return 0
	Local $nbase = Int($narray[1])
	Local $nn = StringLen($narray[2])
	If $nbase = 1 Then Return $nn
	$nnumarray = StringToASCIIArray($narray[2],0, $nn,1)
	Local $exitnum = 0
	For $i = 0 To $nn-1
		$exitnum *= $nbase
		$exitnum += $nnumarray[$i]
		If $nnumarray[$i] > 60 Then
			If ($nnumarray[$i]-55) >= $nbase Then Return 0
			$exitnum -= 55
		Else
			If ($nnumarray[$i]-48) >= $nbase Then Return 0
			$exitnum -= 48
		EndIf
	Next
	Return $exitnum
EndFunc
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
C2H5OH [?]
А вы не знали что существуед единичная система счисления?
знали. но она интереса не представляет, только если ты не ребенок дошкольного возраста, который учиться считать на палочках :smile:
у тебя ошибка в обратной функции. она возвращает 0
 

C2H5OH

AutoIT Гуру
у тебя ошибка в обратной функции. она возвращает 0
Это я на ходу вдруг придумал добавить проверку на то что в числе попалась цифра больше чем основание системы счисления. :-[
Немного не туда поставил эту проверку... Уже исправил. :smile:
 

xCite

Новичок
Наконец-то победил))))
Код:
$x1 = DecToN(200, 6)
$x2 = NToDec("8n500")
MsgBox (0, "", $x1)
MsgBox (0, "", $x2)

Func DecToN($DecNum, $Base)
   Local $Output = ""
   $Del = $DecNum
   While $Del > 0
	  $Ost = Mod($Del, $Base)
	  $Output = Chr(48 + $Ost) & $Output
	  $Del = Int($Del / $Base)
   WEnd
   $Output = $Base & "n" & $Output
   Return $Output
EndFunc

Func NToDec($Input)
   Local $Output = 0
   $BaseAndNum = StringSplit($Input, "n")
   $Base = $BaseAndNum[1]
   $BaseNum = $BaseAndNum[2]
   $NumArray = StringToASCIIArray($BaseNum)
   $Len = StringLen($basenum)
   For $i = 0 To $Len - 1
	  $output = $Output + int(chr($NumArray[$i]) * ($Base ^ (($Len - 1) - $i)))
   Next
   Return $Output
EndFunc

Правда никаких проверок на правильность ввода не делается (в условии этого нет)
 

C2H5OH

AutoIT Гуру
Эээээ, нехорошо подсматривать чужой код...
Ты не используешь фишку ASCII, хотя и вызываешь
Код:
$NumArray = StringToASCIIArray($BaseNum)


Для твоих функций было бы логично использовать второй раз
Код:
$NumArray = StringSplit($BaseNum, "")


А потом вместо мудрёного
Код:
chr($NumArray[$i])

брать просто
Код:
$NumArray[$i]
 

xCite

Новичок
Эээээ, нехорошо подсматривать чужой код...
Ты не используешь фишку ASCII, хотя и вызываешь
Код:
$NumArray = StringToASCIIArray($BaseNum)
тут да, согласен, я редиска)))
мне надо было вывести число по порядковому номеру в строке, но я не знаю как из строки вывести отдельный символ((
а тут смотрю - и библиотеки не подключаются, и работает как надо.
в общем плюсую тебе))

ЗЫ:
А потом вместо мудрёного
Код:
chr($NumArray[$i])

брать просто
Код:
$NumArray[$i]
из
Код:
chr($NumArray[$i])
получаю именно число (от 0 до 9)
а из
Код:
$NumArray[$i]
получается не число а код числа (0 это 48, 1 это 49 и т. д.)

В общем на что мозгов хватило... :whistle:


Добавлено:
Сообщение автоматически объединено:

Убрана похожесть на скрипт C2H5OH
Код:
$x1 = DecToN(200, 6)
$x2 = NToDec("4n10123012")
MsgBox (0, "", $x1)
MsgBox (0, "", $x2)

Func DecToN($DecNum, $Base)
   Local $Output = ""
   $Del = $DecNum
   While $Del > 0
	  $Ost = Mod($Del, $Base)
	  $Output = Chr(48 + $Ost) & $Output
	  $Del = Int($Del / $Base)
   WEnd
   $Output = $Base & "n" & $Output
   Return $Output
EndFunc

Func NToDec($Input)
   Local $Output = 0
   $BaseAndNum = StringSplit($Input, "n")
   $Len = StringLen($BaseAndNum[2])
   For $i = 0 To $Len - 1
	  $tmp = StringMid($BaseAndNum[2], $i+1, 1)
	  $Output = $Output + int($tmp) * ($BaseAndNum[1] ^ (($Len - 1) - $i))
   Next
   Return $Output
EndFunc
 

winstan

Эксплотатор)
Код:
$j=DecToN(18118,9)
ConsoleWrite($j&@CRLF)
ConsoleWrite(NToDec($j)&@CRLF)

Func DecToN($decnum, $base)
	$ret=""
	While Not $decnum=0
		$t=Mod($decnum,$base)
		$decnum=Floor($decnum/$base)
		$ret=$t&$ret
	WEnd
	$ret=$base&"n"&$ret
Return $ret
EndFunc

Func NToDec($nnum)
	$t=StringSplit($nnum,"n",1)
	$arry=StringSplit($t[2],"")
	$ret=0
	For $i=1 To $arry[0]
		$y=$arry[0]-$i
		$ret+=$arry[$i]*$t[1]^$y
	Next
	Return $ret
EndFunc
 
Автор
kaster

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Вобщем, все решили правильно. я надеюсь, никто не обидится если за скоростью исполнения признаю победителем нашего этилового друга :smile:

вот мое решение. отличие от ваших решений - я не использовал конвертацию в ascii, зато использовал богоподобную рекурсию 8)

Код:
Func DecToN($decnum, $base)
	Return $base & 'n' & DecToNRec($decnum, $base)
EndFunc

Func DecToNRec($decnum, $base)
	If $decnum < $base Then
		Return $decnum
	Else
		$decint = Floor($decnum/$base)
		$rem = Mod($decnum, $base)
		Return DecToNRec($decint, $base) & $rem
	EndIf
EndFunc

Func NToDec($nnum)
	$nnum = StringSplit($nnum, 'n')
	$base = $nnum[1]
	$nnum = $nnum[2]
	$n = StringLen($nnum)
	$decnum = 0
	For $i = 1 to $n
		$decnum += Int(StringMid($nnum, $i, 1))*$base^($n - $i)
	Next
	Return $decnum
EndFunc

$decnum = 18118
For $i = 2 to 9
	ConsoleWrite($i & ':' & @TAB & DecToN($decnum, $i) & @CRLF)
Next
 

AZJIO

Меценат
Меценат
Код:
$re=''
For $i = 2 To 9
	$re &= _DecToN('18118', $i)&@LF
Next
$re=StringTrimRight($re, 1)
MsgBox(0, 'Сообщение', $re)

$aNum=StringSplit($re, @LF)
$re=''
For $i = 1 To $aNum[0]
	$re &= _NToDec($aNum[$i])&@LF
Next
MsgBox(0, 'Сообщение', $re)

Func _DecToN($decnum, $base)
	Local $Out, $ost
	Do
		$ost=Mod($decnum, $base)
		$decnum=($decnum-$ost)/$base
		$Out=$ost&$Out
	Until $decnum=0
	Return $base&'n'&$Out
EndFunc

Func _NToDec($nnum)
	Local $aNum, $i, $n, $Out
	$aNum=StringSplit($nnum, 'n')
	If @error Or Not IsArray($aNum) Or $aNum[0]<>2 Then Return SetError(1)
	$n=StringSplit($aNum[2], '')
	For $i = 1 To $n[0]
		$Out += $n[$i]*$aNum[1]^($n[0]-$i)
	Next
	Return $Out
EndFunc


до шестнадцатеричных
Код:
$re=''
For $i = 2 To 16
	$re &= _DecToN('255', $i)&@LF
Next
$re=StringTrimRight($re, 1)
MsgBox(0, 'Сообщение', $re)

$aNum=StringSplit($re, @LF)
; #include <Array.au3>
; _ArrayDisplay($aNum, 'Array')
$re=''
For $i = 1 To $aNum[0]
	$re &= $aNum[$i] & ' - ' & _NToDec($aNum[$i])&@LF
Next
MsgBox(0, 'Сообщение', $re)

Func _DecToN($decnum, $base)
	Local $Out, $ost, $n[16]=['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
	Do
		$ost=Mod($decnum, $base)
		$decnum=($decnum-$ost)/$base
		$Out=$n[$ost]&$Out
	Until $decnum=0
	Return $base&'n'&$Out
EndFunc

Func _NToDec($nnum)
	Local $aNum, $i, $n, $Out
	$aNum=StringSplit($nnum, 'n')
	If @error Or Not IsArray($aNum) Or $aNum[0]<>2 Then Return SetError(1)
	If StringRegExp($aNum[2], '(?i)[A-F]') Then
		$aNum[2]=StringRegExpReplace($aNum[2], '.', '\0,')
		$aNum[2]=StringTrimRight($aNum[2], 1)
		$aNum[2]=StringReplace($aNum[2], 'A', '10')
		$aNum[2]=StringReplace($aNum[2], 'B', '11')
		$aNum[2]=StringReplace($aNum[2], 'C', '12')
		$aNum[2]=StringReplace($aNum[2], 'D', '13')
		$aNum[2]=StringReplace($aNum[2], 'E', '14')
		$aNum[2]=StringReplace($aNum[2], 'F', '15')
		$n=StringSplit($aNum[2], ',')
	Else
		$n=StringSplit($aNum[2], '')
	EndIf
	For $i = 1 To $n[0]
		$Out += $n[$i]*$aNum[1]^($n[0]-$i)
	Next
	Return $Out
EndFunc
 
Верх