Я так делаю
begin
var m := 20;
var a := SeqRandom(1000 * m, 0, 100)
.Distinct.Take(m).ToArray;
a.Println;
end.
В счетчике там все равно что ставить, хотя бы на пару порядков больше m )))
Я так делаю
begin
var m := 20;
var a := SeqRandom(1000 * m, 0, 100)
.Distinct.Take(m).ToArray;
a.Println;
end.
В счетчике там все равно что ставить, хотя бы на пару порядков больше m )))
А с чего вы решили что там не будет повторяющихся чисел?
Это плохо, вероятность маленькая но всё же может сломаться, особенно если возможных значений не так много. В таких случаях всё же лучше бесконечную последовательности делать.
Поставтье 100000000
Я кстати сейчас попробовал… Вот так вообще по феншую:
begin
SeqGen(1,i-> Random(1,100) ).Cycle
.Distinct
.Take(10)
.Print
end.
А если бы массивы можно было бы, то
begin
Range(1, 100).ToArray.Shuffle.Print;
end.
Вообще Range(1, 100).ToArray
работает медленно, оно создаст очень много лишних массивов. Лучше ArrGen(100,i->i+1)
- оно создаст только 1 массив.
Чуть поразбирался с четырьма классами таймеров в NET, и попытался перевести код
// https://professorweb.ru/my/csharp/thread_and_files/1/1_15.php
using System; using System.Threading;
namespace ConsoleApplication8_Timers { class Program { static void PrintTime(object state) { Console.Clear(); Console.WriteLine("Текущее время: "+ DateTime.Now.ToLongTimeString()); }
static void Main()
{
// Делегат для типа Timer
TimerCallback timeCB = new TimerCallback(PrintTime);
Timer time = new Timer(timeCB, null, 0, 1000);
Console.WriteLine("Нажми чтоб выйти");
Console.ReadLine();
}
}
}
получается
uses System.Threading;
procedure PrintTime(state: object);
begin
print('Текущее время: ', DateTime.Now.ToLongTimeString());
end;
begin
// Делегат для типа Timer
var timeCB: TimerCallback = new TimerCallback(PrintTime); //ОШИБКА: нужен объект
var time: timer = new Timer(timeCB, null, 0, 1000);
Print ('Нажми чтоб выйти');
ReadLine();
end.
однако или что-то снова под вечер туплю, или же есть нюанс
Вы не туда поставили ``` у выделения C# кода.
По вопросу - ищите такое на msdn.
TimerCallback
- это тип делегата, то есть процедуры в данном случае. У него есть operator implicit
как у любого другого делегата, для совместимости с другими делегатами у которых такие же параметры и возвращаемое значение:
uses System.Threading;
procedure PrintTime(state: object);
begin
print('Текущее время: ', DateTime.Now.ToLongTimeString());
end;
begin
// Делегат для типа Timer
var timeCB: TimerCallback := PrintTime;
var time: timer = new Timer(timeCB, nil, 0, 1000);//вообще, можно и саму PrintTime передавать в конструктор
Print ('Нажми чтоб выйти');
readln();
end.
Что касается конструктора - я не уверен на 100%, но поидее должно работать так:
uses System.Threading;
type
t1 = class
procedure PrintTime(state: object);
begin
print('Текущее время: ', DateTime.Now.ToLongTimeString());
end;
end;
begin
var a := new t1;
var timeCB: TimerCallback := new TimerCallback(
a,//объект для которого будет вызываться метод. Если метод статичный - передавайте nil
System.Delegate(a.PrintTime).Method.MethodHandle.Value
);
var time: timer = new Timer(timeCB, nil, 0, 1000);
Print('Нажми чтоб выйти');
readln();
end.
(Правда, сейчас получаем внутреннюю ошибку))) #1552)
Кстати, глобальные подпрограммы как в вашей программе - тоже при компиляции превращаются в статичные методы. То есть для них в качестве объекта тоже надо передавать nil
.
Правда, в несколько раз медленнее… Но ведь Range(a, b)
– это родной дотнетовский? Странное поведение такого распространённого генератора…Что ж, спасибо за подсказку, будем знать.
Дело не в генераторе а в том как вы его используете. Range возвращает yield
последовательность, то есть чтоб вычислить её длину - надо пройтись по всем элеметам.
А .ToArray
позволено пройтись по последовательности только 1 раз. То есть перед тем как он узнает сколько всего есть елементов - ему придётся куда то сохранить те элементы по которым он пройдёт. Поэтому он работает так (я декомпилировал):
Создаётся массив на 4 элемента и заполняется. Если не хватило - создаётся массив в 2 раза больше, в него копируется то что есть, предыдущий удаляется и заполнение продолжается для нового массива. Последнее повторяется пока yield
последовательность не скажет что достигли последнего элемента. В самом конце создаётся ещё 1 массив, уже с нужным кол-вом элементов, и в него снова копируется то что прочитали.
Но, кстати, если на вход в .ToArray
подать IList<T>
последовательность (то есть любой список, массив, словарь, всё с известной длиной) - будет создан только 1 массив, нужной длины.
В общем у ленивых вычислений свои применения, а у IList<T>
-ов - свои. К примеру это:
Range(1,100).Sum
Будет лучше чем это (по скорости Range
может капельку медленней, а по памяти - огромное преимущество):
ArrGen(100,i->i+1).Sum
Надеюсь, понятно почему. Если нет - почитайте презентацию по ленивым вычислениям, на pascalabc.net (да название паскаля работает как ссылка). Эту презентацию создавали преподаватели с корочкой, а не самозванцы вроде меня)) Так что там должно рассказываться лучше.
Недавно пользуюсь PascalABC, но часто появляется проблема, когда выполнение программы запускается, компиляция проходит, ошибок нет, программа запущена, но фразы не выводятся в окне вывода. Выглядит это все так:
Win10? Скольки-битная и т.п.?
И - попробуйте удалить .Net4.0 (если установлено) и установить заново (именно 4.0, другие версии не подходят).
Win8 64x Хорошо
О как! Ну да, ему (ToArray
) деваться, в общем-то, некуда если размер заранее неизвестен.
Про ленивость всё ясно, только очень она многоликая, проявляется там, где не ожидаешь
Спасибо за подробный ответ!
А это с чего вдруг? Ленивость возможно только у нескольких типов, специально прописанных.
К примеру, Range
возвращает sequence
, это видно при открытии скобочки и если навести на него мышку. А значит - он будет возвращать ленивую последовательность.
Похоже на антивирус. Запишите рабочую папку паскаля в исключения.
Да это-то ясно. Я имел в виду, что если мало сталкивался с “ленивостью”, то можно сразу не сообразить, что Range(1, 100).ToArray
будет при работе плодить массивы. Привыкать надо такие штуки замечать, я об этом.
Попробуйте декомпилировать свои программы (я использую для этого DotPeek) - найдёте и более интересные штуки)).
Вам пора завести новую тему: интересные штуки Будем с удовольствием читать.
“Кунштюки РАВС”