Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.10.2014, 19:50
Новичок на форуме
Отправить личное сообщение для Scampada Посмотреть профиль Найти все сообщения от Scampada
 
Регистрация: 26.10.2014
Сообщений: 7

str.replace, не понимаю механизм глобальной замены
Привет, народ. Есть функция, которая парсит строку на предмет функций и заменяет их соответствующими значениями.

http://jsfiddle.net/johnthecreeper/ERSA2/116/

Здесь полный код. Вот сама функция:

function specFuncs(expression){
        var funcList = /(sin\(\d+\.?\d*\))|(cos\(\d+\.?\d*\))|(\d+\.?\d*\^\d+\.?\d*)|(\d+\.?\d*\!)/gi;
        expression = expression.replace(funcList, function(match,p1,p2,p3,p4,offset,string){
            switch(match) {
                case p1:
                    return Math.sin(parseFloat(match.replace(/[^\d+?\.\d*?]/gi,""))*(Math.PI/180)).toFixed(10).toString();
                case p2:
                    return Math.cos(parseFloat(match.replace(/[^\d+?\.\d*?]/gi,""))*(Math.PI/180)).toFixed(10).toString();
                case p3:
                    return Math.pow(match.split("^")[0],match.split("^")[1]).toFixed(10).toString();
                case p4:
                    var temp = 1;
                    match = parseInt(match);
                    while(match) temp *= match--; return temp.toFixed(10).toString();
            }
        });
        return expression;
    }


На данный момент все работает, но я пытаюсь обработать такую строку: 2^2^2, после чего получаю результат 4. Добавляю в функцию алерты для выяснения сколько раз и для чего вызывается замена, и получается, что в первый раз функция замены ловит 2^2, а затем отдает на выход функции недорешенную строку 4.00000000^2. Сама по себе такая строка тоже парсится и решается, отдельно. При этом строка, например, вида 2^2 + 2! -3^1 парсится правильно, то есть сначала ловится 2^2, затем все остальное по очереди. И обе части с возведением в степень ловятся, а вот в первом случае, по идее, чем оно отличается? Сначала ловится одно возведение в степень, затем должно парсить строку с промежуточным результатом, найти там еще одну возможность замены и сматчить. Но не делает этого. Почему?
Ответить с цитированием
  #2 (permalink)  
Старый 26.10.2014, 20:32
Профессор
Отправить личное сообщение для kostyanet Посмотреть профиль Найти все сообщения от kostyanet
 
Регистрация: 23.10.2010
Сообщений: 2,718

После замены 2^2 больше нет 2^2, есть только ^2. Не факт что я ответил правильно, и это не важно. Не совсем понял что вы делаете, но если вычисляете выражение по кускам, то делается не так. Просто найдите токенизатор для калькуляторов и не надо свой писать.
Ответить с цитированием
  #3 (permalink)  
Старый 26.10.2014, 20:38
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

Scampada,
пока в строке есть синусы -- они вычисляются - не match нужен а test строки и перезапись первого попавшегося синуса.
потом так-же косинусы
потом находятся первые любые скобки - если они есть - и в них вычисяется пока есть ^ и ! потом * / - + тоже пока есть - вместо скобок получили число -- ищем следующие скобки пока не закончатся -- скобок нет -- прогоняем результрующую строку по этому же алгоритму
^ ! */-+
Ответить с цитированием
  #4 (permalink)  
Старый 26.10.2014, 20:38
Профессор
Отправить личное сообщение для kostyanet Посмотреть профиль Найти все сообщения от kostyanet
 
Регистрация: 23.10.2010
Сообщений: 2,718

Кстати, а вы не пробовали дописать к експрессион 'var result='+ и сделать над всей строкой eval?
Ответить с цитированием
  #5 (permalink)  
Старый 26.10.2014, 20:53
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

Сообщение от kostyanet
Кстати, а вы не пробовали дописать к експрессион 'var result='+ и сделать над всей строкой eval?

Цитата:
Разбор строки осуществляется с помощью регулярных выражений
Ответить с цитированием
  #6 (permalink)  
Старый 26.10.2014, 20:54
Новичок на форуме
Отправить личное сообщение для Scampada Посмотреть профиль Найти все сообщения от Scampada
 
Регистрация: 26.10.2014
Сообщений: 7

Сообщение от kostyanet Посмотреть сообщение
После замены 2^2 больше нет 2^2, есть только ^2. Не факт что я ответил правильно, и это не важно. Не совсем понял что вы делаете, но если вычисляете выражение по кускам, то делается не так. Просто найдите токенизатор для калькуляторов и не надо свой писать.
Нет. Алерт четко показывает, что есть: 4.00000000^2. Просто это выражение дальше не парсится, а отправляется на выход функции, а дальше от строки отрезается только четверка и идет на вывод.
Ответить с цитированием
  #7 (permalink)  
Старый 26.10.2014, 20:55
Новичок на форуме
Отправить личное сообщение для Scampada Посмотреть профиль Найти все сообщения от Scampada
 
Регистрация: 26.10.2014
Сообщений: 7

Сообщение от kostyanet Посмотреть сообщение
Кстати, а вы не пробовали дописать к експрессион 'var result='+ и сделать над всей строкой eval?
Ну, как бы да: в чем тогда будет заключаться моя роль? Этак можно вообще ничего не писать и мозги не парить.
Ответить с цитированием
  #8 (permalink)  
Старый 26.10.2014, 20:57
Новичок на форуме
Отправить личное сообщение для Scampada Посмотреть профиль Найти все сообщения от Scampada
 
Регистрация: 26.10.2014
Сообщений: 7

Сообщение от рони Посмотреть сообщение
Scampada,
пока в строке есть синусы -- они вычисляются - не match нужен а test строки и перезапись первого попавшегося синуса.
потом так-же косинусы
потом находятся первые любые скобки - если они есть - и в них вычисяется пока есть ^ и ! потом * / - + тоже пока есть - вместо скобок получили число -- ищем следующие скобки пока не закончатся -- скобок нет -- прогоняем результрующую строку по этому же алгоритму
^ ! */-+
Немного не понял про match, вернее про то, что он не нужен. Его и нет там вроде. replace как раз вроде и перезаписывает первое попавшееся совпадение и проверяет новую строку на дальнейшие совпадения.
Я вообще-то спрашивал про механизм действия str.replace, по какому принципу она делает глобальную замену...
Ответить с цитированием
  #9 (permalink)  
Старый 26.10.2014, 21:24
Профессор
Отправить личное сообщение для kostyanet Посмотреть профиль Найти все сообщения от kostyanet
 
Регистрация: 23.10.2010
Сообщений: 2,718

Сообщение от Scampada
в чем тогда будет заключаться моя роль?
Ваша роль заключается в том чтобы мозги парить?
Ответить с цитированием
  #10 (permalink)  
Старый 26.10.2014, 21:34
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,105

Scampada,
примерно так без скобок и синусов
function calc(str)
 	{
 	  str = str.replace(/\s+/g, '');
      var re = /(\d+(\.\d+)*)\!/;

 	  for (; re.test(str);) {str = str.replace(re,
      function (a, b)
 	      {
 	        var temp = 1;
            b = parseInt(b);
            while(b) temp *= b--;
            return temp.toFixed(10).toString();
 	      }
 	    )
 	  };

     re = /(\d+\.?\d*)\^(\d+\.?\d*)/;
 	  for (; re.test(str);) {str = str.replace(re,
      function (a, b, c)
 	      {
 	        return Math.pow(b, c).toFixed(10).toString();
 	      }
 	    )
 	  };
      re = /(-*\d+\.?\d*)\/(-*\d+\.?\d*)/;
 	  for (; re.test(str);) {str = str.replace(re,
      function (a, b, c)
 	      {
 	        return (b / c).toFixed(10).toString();
 	      }
 	    )
 	  };

      re = /(-*\d+\.?\d*)\*(-*\d+\.?\d*)/;
 	  for (; re.test(str);) {str = str.replace(re,
      function (a, b, c)
 	      {
 	        return (b * c).toFixed(10).toString();
 	      }
 	    )
 	  };
      re = /(-*\d+\.?\d*)\-(-*\d+\.?\d*)/;
 	  for (; re.test(str);) {str = str.replace(re,
      function (a, b, c)
 	      {
 	        return (b - c).toFixed(10).toString();
 	      }
 	    )
 	  };
      re = /(-*\d+\.?\d*)\+(-*\d+\.?\d*)/;
 	  for (; re.test(str);) {str = str.replace(re,
      function (a, b, c)
 	      {
 	        return (+b + +c).toFixed(10).toString();
 	      }
 	    )
 	  };
 	  return str
 	}
 	alert([calc('2^2^2'),calc('2^2 + 2! -3^1'),calc('-5 + -5')])
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск