Перейти к основному содержимому

Генератор number

Берите его, когда нужно целое число — id, код, цена, возраст — в заданном диапазоне; либо строка ровно из N цифр (даже сотни или тысячи — куда больше, чем вмещает обычный числовой тип).

У генератора number несколько режимов, и выбираются они тем, какие из атрибутов value и length заданы. На этой странице разобран каждый.

Кратко

АтрибутОбязательныйЧто делает
valueнетbit, одно число "50", список "10,20,35", диапазон "100..999" или их смесь
lengthнетФиксированная ширина "10", диапазон "2-10" или группы "2,10-12"
percentнетДоли для групп length, например length="2,10-12" percent="85,15"
first_zeroнетtrue / false — разрешён ли ведущий ноль
includeнетДобавить числа или диапазоны к value
excludeнетУбрать числа или диапазоны из value
decimalsнетЦифр после запятой, 010 — делает колонку дробной

Без value и без length генератор number выдаёт одну случайную цифру 09.

./run demo.tdc
7
2
9
0
4

Один бит

value="bit" даёт случайный 0 или 1 — удобно для булевоподобных флагов.

<gen type="number" value="bit"/>
./run demo.tdc
1
1
1
1
0

Одно число или несколько

value принимает одно число, когда колонка всегда хранит именно его, и список через запятую, когда она хранит одно из нескольких:

<gen type="number" value="50"/> <!-- всегда 50 -->
<gen type="number" value="10,20,35"/> <!-- одно из трёх -->
./run demo.tdc
50        35
50        20
50        35
50        20
50        10

Обе формы существуют, чтобы константа и небольшой набор чисел оставались внутри числового генератора, где числовые атрибуты означают то, что говорят. Раньше здесь не принималась ни одна из них, и написать «всегда 50» можно было только как <gen type="text" value="50"/> — список строк, которые выглядят как число. Это работает и сейчас, но проверка там устроена иначе, и разница существенна: текстовый список проверяется чтением, поэтому value="hello,50" с anomaly= проходит, а потом даёт всплески вдвое реже, чем вы просили, — слово умножить нельзя. В number каждое значение число по построению, поэтому заявленная доля равна фактической.

Диапазон

Задайте value диапазоном от..до (включительно) — и получите случайное целое внутри.

<gen type="number" value="1000..9999"/>
./run demo.tdc
7990
6325
8602
6092
3258

Два правила синтаксиса:

  • Разделитель — всегда .., никогда не одиночный дефис.
  • Одиночный - внутри value — это знак минуса отрицательного числа, поэтому отрицательные диапазоны работают сразу:
<gen type="number" value="-500..-200"/>
./run demo.tdc
-267
-322
-246
-330
-425

Ведущие нули сохраняются

Если диапазон записан с ведущими нулями, ширина сохраняется — удобно для кодов фиксированной ширины:

<gen type="number" value="0000..9999"/>
./run demo.tdc
7767
5916
8446
5658
2509

Несколько диапазонов сразу

Передайте список диапазонов в скобках через запятую — TDC сначала случайно выбирает один диапазон, а затем число внутри него.

<gen type="number" value="[0..100],[345..678],[1934..2026]"/>
./run demo.tdc
1952
662
1975
664
85
Тонкость распределения

В списке диапазонов равновероятен каждый диапазон, а затем равновероятно число внутри выбранного диапазона — поэтому по всему набору отдельные числа распределены неравномерно. Если нужен по-настоящему равномерный выбор по диапазону минус пара «дыр», используйте exclude (ниже).

Фиксированная ширина через length (паддинг)

Когда заданы оба атрибута — value и length, — length работает как ширина вывода: короткие числа дополняются ведущими нулями, длинные печатаются как есть. Сид один, поэтому числа те же — меняется только ширина:

<gen type="number" value="1..999"/> <!-- сырьё -->
<gen type="number" value="1..999" length="4"/> <!-- та же серия, ширина 4 -->
./run demo.tdc
сырьё   length="4"
770  ->  0770
350  ->  0350
79   ->  0079
959  ->  0959
208  ->  0208

Числа не изменились — их просто дополнили до четырёх цифр. В этом режиме паддинга ведущий ноль по умолчанию разрешён (чтобы короткое значение могло добрать ширину).

decimals — дробная колонка

Задача. Цена, ставка, измерение. value="1..999" даёт целые числа; decimals="2" даёт тот же диапазон с двумя цифрами после точки.

<gen type="number" value="1..999" decimals="2"/>
./run price.tdc
776.15
591.50
843.99

decimals принимает целое от 0 до 10. Всё остальное останавливает прогон:

./run price.tdc (decimals="11")
tdcv2: number decimals must be an integer 0..10, got "11"

Он заменяет length, а не дополняет его: у дробного значения нет целой ширины, которую можно добить, поэтому пара — это TDC278:

tdcv2 check price.tdc
error[TDC278]: length="8" is not read beside decimals="2" — a fractional value has no integer width to pad

С include / exclude он тоже не сочетается. Дробная колонка не из плоского диапазона, а по форме распределения — в статистических распределениях.

Режим цифровой строки

Задайте length без value — и генератор переключает режим: он собирает результат по одной цифре и всегда возвращает строку ровно такой длины. Это не JavaScript-число, а текст, поэтому можно генерировать идентификаторы на сотни и тысячи цифр.

<gen type="number" length="10" first_zero="true"/>
./run demo.tdc
7299399441
5929481897
8462586083
5905900972
2876831899

Здесь first_zero="true" разрешает ведущий ноль. Среди этих пяти строк его нет — ведущий ноль выпадает примерно раз из десяти, и на коротком куске его часто не видно. На 200 строках он встречается 16 раз; без атрибута — ни разу. В этом и всё его действие: без него первая цифра в этом режиме нулём не бывает.

Переменная длина

length сам может быть диапазоном или группами с долями:

<gen type="number" length="2-10"/> <!-- случайная длина 2..10 -->
<gen type="number" length="2,10-12" percent="85,15"/> <!-- 85% коротких, 15% длинных -->
./run demo.tdc
length="2-10"            -> 70270136
length="2,10-12" 85/15   -> 77

Здесь percent работает точно так же, как в text: при count="100" ровно 85 значений будут длины 2, а 15 — длины 10–12.

first_zero — управление ведущим нулём

first_zero решает, может ли первая цифра быть 0. Значение по умолчанию зависит от режима:

  • Режим паддингаvalue): ведущий ноль по умолчанию разрешён, чтобы паддинг мог добрать ширину. first_zero="false" его запрещает — тогда TDC берёт значение, у которого и так хватает цифр:
<gen type="number" value="0..9999" length="4"/> <!-- ноль ок -->
<gen type="number" value="0..9999" length="4" first_zero="false"/> <!-- ноль нет -->
./run demo.tdc
по умолчанию   first_zero="false"
7701      ->     7701
3494      ->     3494
0785      ->     2379
9597      ->     9597
2078      ->     2078

Только 0785 (единственное значение, начинавшееся с нуля) заменено на полноценное четырёхзначное 2379; всё остальное и так не имело ведущего нуля и осталось нетронутым.

  • Режим цифровой строки (без value): ведущий ноль по умолчанию запрещён. Передайте first_zero="true", когда строка может начинаться с нуля (десятизначный пример выше).

Добавить и убрать числа: include / exclude

Чтобы не расписывать список поддиапазонов ради пары исключений, используйте exclude (убрать) и include (добавить). Значения — числа или диапазоны a..b через запятую.

<gen type="number" value="0..9" exclude="3"/> <!-- 0–9 кроме 3 -->
<gen type="number" value="1000..9999" exclude="1234,5678"/> <!-- id без этих двух -->
<gen type="number" value="0..100" exclude="40..60"/> <!-- без середины -->
<gen type="number" value="0..9" include="100"/> <!-- 0–9 и ещё 100 -->
./run demo.tdc
value="0..9" exclude="3"               -> 7
value="1000..9999" exclude="1234,5678" -> 7931
value="0..100" exclude="40..60"        -> 82
value="0..9" include="100"             -> 8

Два момента, которые стоит знать:

  • Выбор честно равномерный по всему, что осталось. value="0..9" exclude="3" — это ровно 1/9 на каждое из девяти оставшихся чисел, в отличие от списка диапазонов, где равновероятны диапазоны, а не отдельные числа.
  • У набора нет дробей. include/exclude собирают набор целых чисел и выбирают из него равномерно, поэтому округлять decimals= нечего. Вместе они отклоняются (TDC255) — до этого движок выбрасывал decimals и выдавал целые, не сказав ни слова.
  • За exclude последнее слово. Итоговый набор — (база ∪ include) − exclude, так что число, добавленное через include и убранное через exclude, исчезает. Если после модификаторов ничего не остаётся — это ошибка TDC087.

Этим модификаторам нужен value с диапазоном; на режим цифровой строки (только length) они не действуют.

Подводные камни, всё вместе

  • Диапазоны записываются через .., а не через - (одиночный - — знак минуса).
  • Ширина с ведущими нулями сохраняется: value="0000..9999""0034".
  • Режим цифровой строки возвращает текст, а не число — безопасно для огромных id.
  • В списке диапазонов равномерны диапазоны, а не отдельные числа — для равномерного выбора с «дырами» используйте exclude.

См. также

  • length и first_zero в справочнике атрибутов.
  • Text — тот же механизм точного percent, но для списков.