Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Конвертер (перевод) систем счисления (https://javascript.ru/forum/misc/52624-konverter-perevod-sistem-schisleniya.html)

helloterry8 27.12.2014 18:10

Конвертер (перевод) систем счисления
 
На языке JavaScript написать программу без встроенных функций с использованием условий, циклов и массивов конвертации из десятичной системы счисления в двоичную, восьмеричную и шестнадцатеричную, а так же реализовать конвертацию чисел в обратном направлении.

Помогите понять, где ошибка. Неправильно переводит из 10 в 2, 8 и 16, а в обратном направлении вообще не работает.

<html>
<head>
    <meta charset="utf-8" />
    <title>Конвертёр чисел между системами счисления</title>
<script type="text/javascript">
function translaten() {
var number = document.getElementById('number').value;
var vhod = document.getElementById('input').value;
var vihod = document.getElementById('output').value;
var resultat = "";
	if (vhod == 10 && vihod == 2 || vihod == 8 || vihod == 16) {
var a;
while (number > 0) {
    a = number % vihod;
resultat = resultat + a;
var b;
b=number/vihod;
number=number-Math.ceil(b);
}
alert('Ваш результат - '+resultat);
}
if (vhod == 2 || vhod == 8 || vihod == 16 && vihod == 10) {
var resultat = 0, m = 0, nnazad, n = number.length;
nnazad = n - 1;
var arr=number.split('');
// for (var i=1; i == n; i++) {
var i = 0;
while (i < number.length) {
if (arr[i] == "A") { arr[i] = "10"; }
if (arr[i] == "B") { arr[i] = "11"; }
if (arr[i] == "C") { arr[i] = "12"; }
if (arr[i] == "D") { arr[i] = "13"; }
if (arr[i] == "E") { arr[i] = "14"; }
if (arr[i] == "F") { arr[i] = "15"; }
m = number[i] * Math.pow(input, n);
resultat = m + resultat;
n--;
i++;
alert('Ваш результат - ', resultat);
if (i > nnazad) { 
    alert('Ваш результат - ', resultat, '.'); break; }
} 
//}
}
}
</script>
    <title>Перевод из одной системы счисления в другую</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
        * {
            padding: 0;
        }

        body {
            color: #80e8ff;
            background: #2E69E3;
            text-align: center; /* выравниваем все содержимое body по центру */
        }

        div {
            width: 800px; /* ширина основного блока */
            height: 100%; /* высота для наглядности */
            background: #004A7f; /* цвет блока для наглядности */
            margin: 0 auto; /* задаем отступ слева и справа auto чтобы сработало выравнивание по центру */
        }

        p {
            font-family: courier;
            font-size: 160%;
        }

        .input {
            border: 5px solid #cccccc;
            border-radius: 9px;
            -webkit-border-radius: 9px;
            -moz-border-radius: 3px;
            -khtml-border-radius: 3px;
            background: #ffffff !important;
            outline: none;
            height: 34px;
            width: 220px;
            color: #80e8ff;
            font-size: 16px;
            font-family: Tahoma;
            text-align: right;
        }

        .button {
            background: #2E8CE3;
            padding: 7px 30px;
            font-size: 16px;
            font-weight: bold;
            color: #FFFFFF;
            text-align: center;
            border: solid 1px #73C8F0;
            cursor: pointer;
            border-radius: 5px;
            -moz-border-radius: 5px;
            -webkit-border-radius: 5px;
            background: -moz-linear-gradient(0% 100% 90deg, #2E8CE3, #73C2Fd);
            background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#73C2Fd), to(#2E8CE3));
            box-shadow: inset 0 1px 0 0 #FFFFFF;
            -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
            -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
            border-bottom: 1px solid rgba(0,0,0,0.25);
            text-shadow: 0 -1px 1px rgba(0,0,0,0.25);
        }

            .button:hover {
                background: #80e8ff;
                background: -moz-linear-gradient(0% 100% 90deg, #2E69E3, #59C2FF);
                background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#59C2FF), to(#2E69E3));
            }

            .button:active {
                background: #80e8ff;
                background: -moz-linear-gradient(0% 100% 90deg, #2E69E3, #59C2fF);
                background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#59C2FF), to(#2E69E3));
                box-shadow: inset 1px 1px 0 0 #004A7f;
                -moz-box-shadow: inset 1px 1px 0 0 #004A7f;
                -webkit-box-shadow: inset 1px 1px 0 0 #004A7F;
                padding: 8px 29px 6px 31px;
            }

        .select {
            border: 5px solid #cccccc;
            border-radius: 9px;
            -webkit-border-radius: 9px;
            -moz-border-radius: 3px;
            -khtml-border-radius: 3px;
            background: #ffffff !important;
            outline: none;
            height: 34px;
            width: 60px;
            color: #004A7f;
            font-size: 16px;
            font-family: Tahoma;
        }
    </style>
</head>
<body>
<form>
    <div>
<p><strong>Конвертёр чисел между системами счисления:</strong></p>
        <p> число <input type="text" name="number" id="number"  /> </p> из
<select class="element select medium" id="input" name="input"> 
	   <option value="" selected="selected"></option>
	   <option>2</option>
	   <option>8</option>
	   <option>10</option>
	   <option>16</option>
	</select> системы счисления в
<select class="element select medium" id="output" name="output"> 
	   <option value="" selected="selected"></option>
	   <option>2</option>
	   <option>8</option>
	   <option>10</option>
	   <option>16</option>
	</select> систему счисления
<p><input type="button" value="Перевести" onclick="translaten();" /></p>
        </div>
</form>
</body>
</html>

Опан 28.12.2014 00:24

Я вспомнил, что я когда-то делал такое, когда ещё не знал о существовании toString() пока для перевода из десятичной в любую систему:
<script>
var mas=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L"]; // Можно завершить латинский алфавит, а если не хватит - добавить русский
var mas1=[];
function NumConvert(a,b){
    while(a>=1){
        c=Math.floor(a/b);
        d=a-b*c;
        mas1.push(d);
        a=c;
    }
    var result="";
    for(i=0;i<mas1.length;i++){
        result+=mas[mas1[mas1.length-1-i]]+"";
    }
    alert(result);
}
</script>

Тут аргументы a - число, b - система.

Erolast 28.12.2014 07:49

Опан, а теперь запусти этот код в строгом режиме. Его нельзя использовать.

Malleys 30.12.2014 19:53

<script>
"use strict";
//************************************
// эта функция переводит число из одной в другую систему счисления

function convert(number, fromBase, toBase) {
  return fromDec(toDec(number, fromBase), toBase);
}
function toDec(number, fromBase) {
  var result = 0;
  number = number.toString().toLowerCase().split('');
  for(var index = 0, length = number.length, digit; index < length; index++) {
    digit = prepareDigit(number[index]);
    result = result * fromBase + digit;
  }
  return result;
}
function fromDec(number, toBase) {
  var result = [], integerPart, digit;
  while(number >= 1) {
    integerPart = parseInt(number/toBase);
    digit = number - toBase * integerPart;
    if(digit >= 10)
      digit = String.fromCharCode(digit + 87);
    result.unshift(digit);
    number = integerPart;
  }

  return result.join('');
}
function prepareDigit(digit) {
  digit = digit.charCodeAt() - 48;
  if(digit > 48)
    digit -= 39;
  return digit;
}

//**********************************

function onClick(q) {
  var BASES = {
    'bin': '2',
    'oct': '8',
    'dec': '10',
    'hex': '16' 
  };
  var PATTERN = /([\dabcdef]+)(?:\s*(?:from|из|\s)(?:\s*base)?\s*(\d+|bin|oct|dec|hex))?\s*(?:(?:to|в)(?:\s*base)?\s*(\d+|bin|oct|dec|hex))?/;
  var PATTERN_BASE = /bin|oct|dec|hex/;
  var value = document.getElementById('inpution').value || q || '';
  var match = value.match(PATTERN);
  var number = match && match[1] || '0';
  var from = match && match[2];
  var to = match && match[3];

  if(PATTERN_BASE.test(from)) {
    from = BASES[from];
  }

  if(PATTERN_BASE.test(to)) {
    to = BASES[to];
  }

  from = +from || 10;
  to = +to || 10;
  var result = convert(number, from , to);
  document.getElementById('result').innerHTML = 'convert <span class="hightlight">' + number.toUpperCase() + '<sub>' + (from == 10 ? '' : from) + '</sub></span> to <span class="hightlight">base ' + to + '</span> = ' + result.toUpperCase() + '<sub>' + (to == 10 ? '' : to)  + '</sub>';
}
  
function example(q) {
  document.getElementById('inpution').value = q;
  onClick();
}
</script>
<style>
#result, #examples {font-family: monospace; font-size: 18px; color: #aaa; }
#examples a:link, #examples a:visited {text-decoration: none; display: block; font-size: 14px; }
#examples a:hover, #examples a:focus {text-decoration: underline; }
#result .hightlight {color: #000; }
#result sub {font-size: 12px; }
#examples {float: left; margin-left: 20px; }
#examples .description {font-size: 12px; }
</style>
<div style="float: left; ">
  <input id="inpution" type="text" value="125 base 10 to base 2" />
  <input id="button" type="button" value="=" onclick="onClick(); " />
  <div id="result"></div>
</div>
<div id="examples">
  <span>Примеры</span>
  <div class="description">Из десятичной в другую систему счисления</div>
  <a href="#" onclick="example('147 to base 2');">147 to base 2</a>
  <a href="#" onclick="example('1025 to base 5');">1025 to base 5</a>
  <a href="#" onclick="example('255 to base 16');">255 to base 16</a>
  <div class="description">Из данной в 10-ую систему счисления</div>
  <a href="#" onclick="example('1000101011 base 2');">1000101011 base 2</a>
  <a href="#" onclick="example('fff base 16');">fff base 16</a>
  <div class="description">Из одной в другую систему счисления</div>
  <a href="#" onclick="example('1424 base 5 to base 12');">1424 base 5 to base 12</a>
</div>

Rise 30.12.2014 20:09

Malleys,
Цитата:

без встроенных функций с использованием условий, циклов и массивов

Malleys 30.12.2014 20:21

Цитата:

Сообщение от Rise
без встроенных функций с использованием условий, циклов и массивов

Сама функция convert их не содержит (строки 5 по 7)
Остальное относится к вводу-выводу информации на странице, каждый может заменить на своё.

Rise 30.12.2014 20:30

Malleys, а это parseInt() и toString() че?

Malleys 11.05.2018 22:24

Цитата:

Сообщение от Pao
Мне [...] необходимо реализовать подобное, не могли бы вы объяснить или прокомментировать свой код, если не составит труда.

Ещё примеры запросов, которые выше не указаны
Перевести 1024 в двоичную систему: 1024 to bin
Перевести шестнадцатиричное FF в десятичную систему: FF hex
Перевести десятичное 25 в восьмеричную систему: 25 dec to oct

С 3-ей по 38-ую строки описаны четыре функций, которые позволяют перевести число из одной системы счисления в другую. Главная из них — convert, которая осуществляет перевод, остальные три — вспомогательные.

Функция convert, берёт число number по основанию fromBase и переводит его в десятичную систему. (Осуществляется при помощи toDec(number, fromBase), строка 7)

Затем полученное десятичное число переводится в систему счисления toBase при помощи функций fromDec, которая берёт десятичное число и переводит его в указанную во втором параметре систему счисления.

В функции toDec (строки 9-17) для перевода в десятичную систему вычисляется сумма произведения цифры на основание возведённое в степень, соответствующей позиции цифры. Для упрощения вычисления используется правило Горнера. Поскольку «цифрой» являются строки "0", "1", ..., "9", "a", "b", ..., "f", то для перевода этих «цифр» используется вспомогательная функция prepareDigit (строки 31-36), которая переводит «цифру» в её десятичное представление. Для этого используется код символа. Символу "0" соответствует код 48, "1" соответствует 49, ..., "9" соответствует 57. Отняв от кода символов число 48 (строка 32), мы получим число соответствующее числовому значению строки. Такое срабатывает только для "0", "1", ..., "9". Коды же символов "a", "b", ..., "f" равны соответственно 97, 98, ..., 102. Поскольку мы уже отняли 48, то у нас соответственно имеется 49, 50, ..., 54. Поэтому проверяется (строка 33) равна ли «цифра» числу большему чем 48. Если это действительно так, то следует ещё отнять 39. (Чтобы из ряда 49, 50, ..., 54 получился ряд 10, 11, ..., 15). Короче говоря, функция prepareDigit для ряда переданных ей значении "0", "1", ..., "9", "a", "b", ..., "f" возвращает 1, 2, ..., 9, 10, 11, ..., 15 соответственно.

В функции fromDec (строки 18-30) используется алгоритм[1] перевода десятичного числа в соответствующее основание.
  • Последовательно делится целая часть десятичного числа на основание, пока десятичное число не станет равно нулю (или пока оно больше или равно 1).
  • Полученные при делении остатки являются «цифрами» нужного числа. Число в новой системе записывают, начиная с последнего остатка.
Притом если «цифра» больше или равна 10, то вместо 10, 11, ..., 15 используется "a", "b", ..., "f" соответственно. (строки 23 и 24, поскольку код "a" равен 97, то следует прибавлять 87, чтобы получить соответствующии символ)

[1] https://ru.wikipedia.org/w/index.php...oldid=91753916

С 40-ой по 67-ую строки описана функция, которая вызывается каждый раз, когда человек нажимает на кнопку «=».

В 49-ой строке переменной value присваивается то, что ввёл человек в текстовое поле.
Затем (50-ая строка) проверяется, подходит ли введённый текст под регулярное выражение, описанное в 47-ой строке, и в переменную match записываются результаты. Данное регулярное выражение, визуально можно представить так: https://regexper.com/#%2F%28%5B%5Cda...ex%29%29%3F%2F

NB!!! Числа, которые совпали в регулярном выражении имеют тип String, т. е. это число которое записано как последовательность символов и представляет из себя строку.

Первая группа в этом регулярном выражении обозначает число, которое нужно перевести. Оно состоит из одной или более цифр, а также символов A, B, C, D, E и F. Это значит, что для перевода подходит любое целое неотрицательное число из систем счисления от 2 до 16 включительно.

В случае, когда человек ввёл запрос, который подходит под выражение (и переменная match не равна null), переменной number присваивается число, которое нужно перевести, иначе присваивается '0' (строка 51)

Вторая и третья группы обозначают сами системы счисления, которые присваиваются переменным from и to (строки 52 и 53).

Когда from или to это не числа (проверяется в 55-61 строках, регулярное выражение для проверки в 48-ой строке), а краткое обозначение двоичной, восьмеричной, десятичной или шестнадцатеричной системы счисления, то такое обозначение преобразуется в число согласно описанию в 41-46 строках. Соответственно теперь в переменных from или to содержатся только числа обозначающие систему счисления.

Согласно регулярному выражению на 47-ой строке, 2-ая и/или 3-яя группы могут отсутствовать. Тогда считается, что число преобразуется из/в десятичную систему. (строки 63 и 64, «+» перед строкой, представляющей из себя число, означает, что это теперь будет число типа Number)

Теперь известны число (number), система счисления этого числа (from), и система, в которую нужно перевести это число (to). Используя вышеупомянутую функцию convert, производится перевод и записывается в переменную result — результат готов. (строка 65)

В 66-ой строке немного «синтактической криптографии», которая печатает на странице результат. Сначала печатается, что удалось выудить из того, что ввёл человек (типа компьютер говорит, я вас понял вот таким образом), затем после знака равно записан результат перевода.

Строки 69-72, которые описывают функцию вставляющую в текстовое поле какой-либо запрос и выполняющую его, нужны только для запуска примеров на 88-99 строках.

Цитата:

Сообщение от Rise (Сообщение 348999)
Malleys, а это parseInt() и toString() че?

Здесь не используется особенность функциий parseInt (строка 21), чтобы перевести из какой-то системы в десятичную...скорей отбрасывается десятичная точка и все цифры после неё, не обращая внимания на знак аргумента. Статичная функция Math.trunc, которая делает именно то, что было нужно, была стандартизирована только спустя полгода после написания вышеприведённого кода (ECMA-262 6th Edition / June 2015) (Хотя вариант (number/toBase) | 0 тоже подходит)

Метод toString на 11-ой строке, применялся именно для того, чтобы гарантированно была строка в том месте. Можно было бы написать вместо number.toString() так: ("" + number) или String(number)

Во всяком случае ни parseInt ни toString не применялись, чтобы использовать встроенные возможности перевода из одной системы счисления в другую.


Часовой пояс GMT +3, время: 20:34.