Найти ближайшее число 1с
Пример 1. Создадим числовую переменную
Преобразование значений другого типа в число
Преобразовать в число можно значения строкового типа, либо логического типа (Булево). Значение типа Булево преобразуется в число по следующим правилам:
- Ложь преобразуется в 0;
- Истина преобразуется в 1.
Значение типа Строка преобразуется в число в том случае, если оно является строковым представлением литерала численного типа.
После выполнения данного кода в переменной ПолученноеЧисло будет содержаться числовое значение 1.25
Функции работы со значениями типа Число в 1с 8.3
В данном разделе будут рассмотрены основные функции работы с числами в 1с 8 и приведены примеры их использования.
Цел(<Число>). Возвращает целую часть числа переданного в параметре.
Пример 4. Определить делится ли число 121 на 11.
Окр(<Число>, <Разрядность>, <РежимОкругления>). Функция округляет число, переданное в первом параметре, до знака после запятой переданного во втором параметре. Значение разрядности может быть и нулевым (округление до целого) и отрицательным (округление до соответствующего разряда целой части). Параметр РежимОкругления может принимать значения:
- 0 (или РежимОкругления.Окр15как10). Округляет в меньшую сторону, то есть при округлении 1.5 будет возвращено 1;
- 1 (или РежимОкругления.Окр15как20). Округляет в большую сторону, то есть при округлении 1.5 будет возвращено 2;
Пример 5. Для того чтобы лучше разобраться с принципами округления рассмотрим округление до целого в меньшую и большую стороны, на ряде чисел от 1.1 до 1.9
Pow(<Основание>, <Показатель>). Возводит число переданное в первом параметре в степень переданную во втором параметре.
Пример 6. Извлечь квадратный корень из числа 144, а затем возвести его в квадрат, в итоге снова должно получится число 144.
Дано: много строк (>10000), длина каждой < 40 символов, могут содержать любые алфавитно-цифровые символы, точки и запятые.
Задача: нужно максимально быстро определить, является ли эта строка числом. При этом строка, являющаяся числом, может содержать нули в старших разрядах и нули на хвосте дробной части. Разделителем разрядов может быть как точка, так и запятая. Знака изначально в строке быть не может, поэтому на + и - пофиг.
Например числа:
0100,99900
100
100.99
Не числа:
100.0,12
Asd100xЩ
100.0Ю
Предложите быстрый алгоритм, плз?
умножить на любое число, например 1. если ругнётся - не число.
Попытка, Исключение
(1) Не. Стр*1 - Операция умножения не определена для строковых величин, 1*Стр - умножит всегда, преобразовав по правилам Число()
Если б не нули в начале и конце, прокатило бы:
.
с предварительной заменой запятой на точку. А с нулями - хз.
Очень не хочется посимвольно разбирать строку, ибо много их.
(6) п. 1 - я сходу вижу только посимвольным разбором. Чего как-раз и не хочется. Как быстро нули посчитать?
(7) Игра ума. Лучше алгоритм предложи. Быстрый.
(8) Потому что Число("123") - это число. А число не равно строке. Засунь в конфигуратор - увидишь.
(10) Это написано в (3). Для строки "0100" условие не выполняется. Я ж говорю - проблема в нулях.
(12)не взлетит
(11) без посимвольного не обойтись, на этапе отсечения нулей - перебор будет короче всего
(12) Повезло тебе, что не на китайском пишешь. У них там, грят, около 5000 основных иероглифов. У какая длинная строка с Найти() была бы ;)
если (3) катит с предварительной заменой точек и запятых.
то замени в исходной строке Стр все "0" на любую другую цифирь
(0) а в принципе, как такая задача родилась?
Тест что ли какой-то?
(18) скорее всего автор хочет привести все Наименования какого-то Справочника к числовому виду
(19)Скорее, коды. Когда нарушают уникальность, потом начинают вводить всякую чепуху.
(20) м.б. автор хочет производить какие-то матоперации с наименованиями.
м.б. это лотерейные билеты или номера скидочных карточек покупателя.
(21) коды я отмёл сразу - (22) прав. самое бОлшее я видел 15 знаков кода.
(22) хотя да.
(23) жизни вы не видели, я видела 100:) Они туда закодировали производителя, иерархию и пр.
(24) Боже!
а зачем же так код мучать? реквизит в Справочник нельзя добавить?
(23) На мой взгляд, для решения этой задачи, надо знать полностью условие, потому как от условий возможна разная реализация, сама по себе задача решаема в лоб без всяких проблем, если она единовременная, то можно плюнуть на быстродействие. Допустим, если автор действительно хочет "перекодировать" справочник, то нужен дополнительный алгоритм, потому как при использовании одного алгоритма преобразования строки состоящей из одних цифр или из цифр и каких-то символов в число, может "задвоится" число, т.е. при одинаковом преобразовании строки цифр и строки символов имеем вероятность получить на выходе одно и то же число.
(28) логично. об уникальности я не подумал.
0099.9, 099.9, 99.990 дадут одно число 99.9
Если нужно просто "достать число" - то есть очень простой способ извлечения числа из строки, без перебора.
ре.test(вСтрока)
В точности не уверен, можно потестировать если надо.
(42) Я понял, что нужно еще определить само значение если строка является числом.
(45) :-)
0 будет только если проверяемое выражение начинается не с цифры. А все первые цифры буду превращаться в число, остальное отбрасываться.
(53) Ограничение знаков после запятой. Для 1С это не число
В терминах поставленной задачи эта строка - число, со значением в 1С, равным нулю.
"1.00000000000000000001" - числом.
Потому как все попытки сравнивать строки до и после преобразования функцией "Число", натыкаются на ограниченность разрядов.
(57) можно и не определяться, по такому принципоу пойти
Число("1"+".000000000000000000001"+"1")*10000000000000000000000
(58) не фигня, так многое можно определить и не только строка или число
(59)
Число("1"+"9876543210"+"1")*1000000000000000000000000000000000000000 =
198765432101000000000000000000000000000000000000000
(58)(59) а это - Число("1толиДатолиНет"+".000000000000000000001"+"1")*10000000000000000000000 число ?
(61) Не, ну понятно. Я сказал что принцып такой. Позицию разделителя дробной найти.
(53) Как я понял, 1С не видит больше 20 знаков после точки.
Тогда можно извернуться так.
Часть вторая.усовершенствованная :-):
--------------------
Ну, ладно, это я уже стебаюсь.
Имхо можно эти способы объединить или выбрать более удобный для (0).
КодСимв(<?>)
Синтаксис:
КодСимв(<Символ>)
Назначение:
Возвращает код первого символа, содержащегося в строке.
Параметры:
<Символ> - строковое выражение.
(67)
То и вернет, что строка является числом, и его значение.
Фишка в том, что число в 1С ограниченно 69 разрядами (чего хватает для этой задачи), но при преобразовании его в строку обрезает до 23 знаков после запятой.
(66)
Неправильно отработает, если будет две точки, и они попадут в разные части.
Либо в середине строки будут пробелы, которые попадут в первую часть в конец, во вторую часть в начало.
(71) Легко решается несколькими строками в начале процедуры Сформировать
:-)
не всеже объясните тупым и алкоголикам чем шаблон плох ? медленно ?
(75) Только еще одно уловие поставить надо, если нет дробной части. Просто хотелось не перебором.
(74) Ну чего ты этими шаблонами добьешься? Попробуй че нить подсунуть. К примеру 00А00.5115.1
(76) Не надо доп. условий, там в комментарии пояснено, почему не надо. И перебора там нет - СтрЗаменить-то без перебора работает.
(78) Спортивно средствами встроенного языка.
такое чувство, что из предложенных вриантов не все тестировали (больше писали на угад) + кто скажет что быстрее ? :)
П.С. сам пока думаю. :)
Мда. Не ожидал я такого спортивного интереса, когда тему поднимал :)
Сразу повторю свой ответ на вопрос "а на хрена?" - это действительно игра ума :) Была реальная, но разовая задача, сделал ее "в лоб" перебором, потом стало интересно, а как быстрее, поставил граничные условия, запостил сюда, пошел домой спать :)
Самый быстрый вариант, как ни странно, оказался самым первым, у 2Green. Но он не работает с числами >20 знаков. Результат меня сильно удивил, потому как я думал о первом варианте Рэйва.
Замер производительности показал:
(В тиках - 110 и 117 соответственно)
Дальше идет вариант с регулярными выражениями (154 тика), вариант orefkov'а (187 тиков), вариант Пуделя (551 тик). Остальные варианты пока не померил.
(84) с регулярами заметь, можно весь тект за один присест, не построчно, "рассортировать".
(84) Блин, ты просто моё время с временем Сообщить замерял :))). Я только что проверил - у меня быстрее орефкова (моё 0.004647, орефкова 0.004695)
(84) Попробуй вариант для регулярных не по одной строке, а по "тексту" т.е. строке разделенной "РазделительСтрок". Если конечно в условия задачи вползает.
Да с Шаблон медленно когда не число зато код простой, можна и еще просче :)
.
(88) Не-а. Правда твой код я переписал, оставил только идею:
(87) Надо "тестовый стенд" для этого переписывать. Сейчас он выглядит так:
1. Исходные данные живут в дбф. 10000 строк. Строки формировались так:
1.1. Случайная длина строки от 1 до 40
1.2. Каждый символ строки генерировался случайным образом из набора "01234567890.,AB". Такой набор получил опытным путем - меня устроил процент "правильных" чисел:
15% (точнее - 1360 из 10000)
1.3. Массив строк хранится в глобальной переменной и перед началом работы считывается из dbf
2. Все алгоритмы загонялись в функцию, возвращающую количество чисел в наборе. Шаблон функции:
(84) ну, с учётом что исходные строки длиной <40, и что ограничение на дробную часть в 20 знаков.
можно добавить Лев(Стр,20) и Прав(Стр,20)
Строки сравниваются посимвольно по коду символа, для ясности несколько примеров "Строка12" < "Строка2", "8.3.9.2000" > "8.3.8", "8.3.9.2000" > "8.3.10"
С учетом регистра можно сравнить строки через знаки сравнения как в примерах
Сравнение без учета регистра можно произвести функций СтрСравнить. Поддерживается с платформы 8.3.6.
- -1 - первая строка меньше второй
- 1 - первая строка больше второй.
- 0 - первая строка равна второй
Преобразование в строку (Строка, Формат)
В языке 1С есть автоматическое преобразование типа когда все части выражения приводятся к типу первого выражения
Преобразование функцией Строка
при преобразовании появляется символ неразрывный пробел, а он обычно не нужен
"Правильнее" будет преобразовывать функцией формат, которая приводит к строке простые типы и можно воспользоватся конструктором
Строка на разных языках НСтр
Форматирование строки по шаблону СтрШаблон. Поддерживается с платформы 8.3.6.
Очень полезная функция которая позволяет избежать соединения строк и сделать текст более читабельным
Функции СтрСоединить, СтрРазделить. Поддерживается с платформы 8.3.6.
Очень полезные функции улучшают читаемость кода.
СтрРазделить удобна когда необходимо разобрать строку с разделителями, например CSV файл, разбор текста на слова, строки
Аналогично, только наоборот работает функция СтрСоединить, преобразуя массив к строке.
Другие функции работы со строками, которые могут быть полезныСтрСократить (Текст, Количество, Многострочная = Ложь) - сокращает текст до заданной длины заменяя окончание на .
ЭтоКорректныйИдентификатор (Строка) - Проверяет является ли строка корректным идентификатором, строка вида СуммаКонтрагента, _Идентификатор
Когда в 1с встает вопрос разбора большого текста это уже зоопарк из СтрДлина, Сред, СтрНайти для повышения читаемости программ для подобных задач использую свои функции: РазборПрочитатьЦелоеЧисло, РазборПрочитатьШестнадцатеричноеЧисло, РазборПрочитатьНезначимые, РазборПрочитатьИдентификатор,
РазборПропуститьНаборСимволов, РазборПрочитатьСимвол, РазборПрочитатьДоСимвола, РазборНайтиТекст
Приветствую. Вот суть задачи:
Есть функция findClosest, которая принимает неотсортированный массив чисел, число которое надо найти и функцию-компаратор. Компаратор должен определять одно из 4 возможных типов поведения для findClosest:
- находить ближайшее меньшее число
- находить ближайшее большее число
- находить ближайшее число, но если оно равноудалено от значений массива, брать то, что меньше
- находить ближайшее число, но если оно равноудалено от значений массива, брать то, что больше
Какие есть изящные решения?
Оценить 6 комментариев
На ум приходит бинарное дерево (bst). Надо будет проверить догадку.Алексей Струков: как в обычном бинарном дереве: слева от вершины - числа меньше, справа - больше. В зависимости от компаратора двигаться по левой или правой стороне. Но это набросок идеи - возможно я не прав.
Кстати, поиск самого числа не обязательно делать в дереве. Разумнее использовать словарь (доступ за O(1)). А дерево заюзать для поиска ближайшего меньшего/большего.
Вот решение, которое я нашел (если кому понадобится в будущем):
Вот так выглядит объект settings c четырьмя возможными компараторами:
И сам вызов функции:
PS:
Вместо false, в случае когда результат не определен, я решил возвращать undefined, так как это значение ближе по семантике.
Для третьего и четвёртого варианта невозможно из компаратора узнать был ли уже на таком же расстоянии.
Выход который я вижу: "сместить" в пользу "низа", но это возможно только с определённой точностью.
Второй вариант: можно сделать если передавать в компаратор три значения: текущее, лучшее сейчас, и то что ищем.
Далее код для a, b - текущее, то что ищем соответственно.
Код не проверял.
Читайте также: