Страницы: 1
RSS
Разбить диапазон чисел по разрядам
 
Всем добрый день!
Поискав на форуме не нашел ничего про преобразование диапазона чисел в регулярные выражения.
Если у кого-то есть - буду благодарен.
Ну а пока, решил сделать его сам.
В процессе наткнулся на задачку, к которой не могу найти подход.
Нужно разбить диапазон чисел по разрядам:
Единицы должны переходить в десятки, десятки в сотни. Потом в обратную сторону до конечного значения. Итак:

Например есть диапазон: 778 - 877 (99 значений)
Необходимо его разбить следующим образом:

778-779 (2 значения) - диапазон до изменения второго разряда (десятки) (меняется с 7 на 8, так как единица обнуляется после значения 9. следующее число будет уже 780)

780-799 (19 значений) - диапазон до изменения первого разряда (после 799 идет 800: первый разряд переходит с 7 на 8 )

Так, как нам не нужен диапазон 9хх (у нас край диапазона - 877 см. условие), то идем в обратную сторону:

800-869 - (69 значений) - диапазон до изменения второго разряда (десятки) (после 869 идет 870)
870-877 - (7 значений) - диапазон до конца.

Вот такая интересная нетривиальная задачка.
На входе - диапазон значений ( в одной ячейке ОТ в другой ДО), на выходе - 4 диапазона в ячейках
В идеале - инструмент должен быть универсальный - диапазоны могут быть четырехзначные, пятизначные и т.п

Я начал диапазоны в массивы заносить, потом пытался сравнивать..в итоге запутался окончательно! )
Может есть какая-то готовая математическая функция? Может похожая? я сам адаптирую ее

Если есть любители поломать голову - буду благодарен  :)
Изменено: mant - 06.09.2016 12:44:05
 
Любители найдутся, если пример будет в файле Excel
 
Сорри, приложил недоделаный макрос
 
Т.е. дан ряд идущих подряд упорядоченных по возрастанию чисел, и признак окончания очередного диапазона - это момент перехода с 6 на 7 или с 7 на 8 в любом разряде кроме первого? Если так, то не понимаю, в чём нетривиальность задачи.
 
Ну, в принципе верно. Только переход с 6 на 7 или 7 на 8 - это в данном конкретном примере. А в общем случае признак -  изменение на единицу сначала единиц, потом десяток, потом сотен
 
Цитата
mant написал:в общем случае признак -  изменение на единицу сначала единиц, потом десяток, потом сотен
В этом "общем" случае все диапазоны будут состоять из одного числа. Т.е. это не общий случай, а частный.
 
В общем пока алгоритм вижу такой. Объявляете массив чисел. В него записываете все числа, которые нужно разбить на диапазоны. Потом циклом проходите по всему этому массиву и сравниваете разряды в текущем элементе массива с разрядами предыдущего элемента массива. Если в результе сравнения выполнилось условие окончания текущего диапазоны и начала следующего, то начинаете записываете текущий элемент массива в новый столбец / новую строку таблицы Excel. Для разделения числа на разряды можно использовать такой способ:
Код
x = 12345 ' число, которое разбиваем на разряды
Do While (x >= 10)
  y = x - Int(x / 10) * 10
  MsgBox (y)
  x = Int(x / 10)
Loop
MsgBox (x)
 
 
рекурсивная функция
Код
Function SplitDigitRange(mi&, ma&, Optional r% = 1, Optional dr% = 1, Optional s$ = "") As String
  Dim v&, i&, u&
  If Int(Log(ma) / Log(10)) < r Then dr = -1
  i = Int(mi / 10 ^ r) * 10 ^ r:  u = i + 10 ^ r - 1:
  u = IIf(u < ma, u, Int(ma / 10 ^ (r - 1)) * 10 ^ (r - 1) - IIf(r = 1, 0, 1)):  If mi = ma Then u = ma
  s = s & ", " & mi & "-" & u
  If r + dr = 0 Or u = ma Then SplitDigitRange = Right(s, Len(s) - 2) Else SplitDigitRange = SplitDigitRange(u + 1, ma, r + dr, dr, s)
End Function

Пример вызова SplitDigitRange
Код
Sub Split()
  Debug.Print SplitDigitRange(112, 53741)
End Sub

Debug.Print распечатал это:
112-119, 120-199, 200-999, 1000-9999, 10000-49999, 50000-52999, 53000-53699, 53700-53739, 53740-53741
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Equio - спасибо. Ваш способ делить длинное число на цифры оригинальнее моего.  :) Взял на вооружение, спасибо!
Подход по сравнению массивов я и думал реализовать, но запутался в самом процессе((
Ігор Гончаренко, Спасибо за функцию! Однако, она возвращает одно лишнее значение. На уменьшение нужно идти на один шаг раньше

Вот диапазон, который я вставил: 778-877
Результат функции: То, что выделил жирным - лишняя итерация
В обратную сторону на единицу шаг не нужен. Остальное все супер. Можно это как-то поправить? или нарушится логика функции и лучше потом уже из текстового результата это лишнее значение вырезать?
"778-779, 780-799, 800-799, 800-869, 870-877"
 
вот еще одна рекурсивная функция, которая разобьет число на разряды
Код
Function DgtCap$(d$)
  If Len(d) > 1 Then DgtCap = "+" & Left(d, 1) & String(Len(d) - 1, "0") & DgtCap(Right(d, Len(d) - 1)) Else DgtCap = "+" & d
End Function

конвертируем число в строку и передаем в функцию
Код
Sub SplitCapacity()
  Debug.Print 12345 & " = " & DgtCap(CStr(12345))
End Sub
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Код
Function SplitDigitRange(mi&, ma&, Optional r% = 1, Optional dr% = 1, Optional s$ = "") As String
  Dim u&, r1%
  If mi >= ma Then SplitDigitRange = Right(s, Len(s) - 2): Exit Function
  u = Int(mi / 10 ^ r) * 10 ^ r + 10 ^ r - 1:  r1 = r:  If u >= ma Then dr = -1
  Do While (u > ma And r1 > 0) Or u < mi
    r1 = r1 - 1:  u = Int(ma / 10 ^ r1) * 10 ^ r1 - IIf(r1 = 0, 0, 1)
  Loop
  s = s & ", " & mi & "-" & u
  If r + dr = 0 Then SplitDigitRange = Right(s, Len(s) - 2) Else SplitDigitRange = SplitDigitRange(u + 1, ma, r + dr, dr, s)
End Function

Sub Split1()
  Debug.Print SplitDigitRange(778, 877)
End Sub

Debug.Print SplitDigitRange(778, 877) = 778-779, 780-799, 800-869, 870-877
Изменено: Ігор Гончаренко - 07.09.2016 15:52:02
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
 
Ігор Гончаренко, не получается в обратную сторону
если вести другой интервал: 501-699
dubug: 501-509, 510-599, 600-689, 690-699 - жирный шрифт - лишнее
В сторону уменьшения от идет через десятки. Здесь нужен последний интервал - 600-699. Последнее значение, после которого 6 переходит в 7
 
поправьте немного макрос и все заработает как нужно
Программисты - это люди, решающие проблемы, о существовании которых Вы не подозревали, методами, которых Вы не понимаете!
Страницы: 1
Читают тему
Наверх