powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel: Разбить число на N случайных составляющих...
13 сообщений из 13, страница 1 из 1
Excel: Разбить число на N случайных составляющих...
    #32932245
kanalex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть ли в Excel такая функция?
Если нет, то нужен алгоритм, который получает на входе 3 числа (скажем 10000, 21, 10%) и разбивает первое число на N (второй аргумент) случайных составляющих так, чтобы каждая из них отличалась от среднего не более чем на Y%(третий аргумент)...
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32933190
Processor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kanalexЕсть ли в Excel такая функция?
Скорее всего, нет.
To kanalexнужен алгоритм, который получает на входе 3 числа (скажем 10000, 21, 10%) и разбивает первое число на N (второй аргумент) случайных составляющих так, чтобы каждая из них отличалась от среднего не более чем на Y%(третий аргумент)..."Не перекладывайте с больной головы на здоровые!"
Это Вам задали такое задание?
Следуйте от постановки задачи: в ней есть 50% ответа.
1. Получите среднее ("...отличалась от среднего...").
2. Используя ДСЧ, получите N-1 случайное число с Y-отклонением.
3. N-е число= разность исходного и суммы первых N-1.
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32933726
kanalex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Processor
"Не перекладывайте с больной головы на здоровые!"
Это Вам задали такое задание?
Следуйте от постановки задачи: в ней есть 50% ответа.
1. Получите среднее ("...отличалась от среднего...").
2. Используя ДСЧ, получите N-1 случайное число с Y-отклонением.
3. N-е число= разность исходного и суммы первых N-1.

Голова действительно больная:), а задание не задали - я его сам себе придумал... Есть, конечно, и практическое применение.

Задача не так проста, как кажется на первый взгляд.:(
По предложенному Вами алгоритму мы действительно получаем N-1

случайных чисел удовлетворяющих условиям задачи, но вот последнее число с большой долей вероятности за эти пределы вылетает:(
И дело тут в разбросе чисел, которые возвращает стандартный ДСЧ. Представьте себе, что все эти числа получились близкими к 1... В итоге набежит Сумма большая, чем нам нужно получить и замыкающее число будет вовсе отрицательным...

Идея понятна?
Что с этим делать? Я не знаю:(
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32934281
Processor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kanalexИдея понятна? Что с этим делать? Я не знаю:(1. Идея понятна.
2. Изложенные Вами страхи базируются на недостаточном опыте работы со случайными числами и их распределениями.
Вы утверждаете "Сумма большая, чем нам нужно...".
Я утверждаю:"Сумма меньшая, чем нам нужно...".
И мы будем оба правы с вероятностью 0,5.

Поскольку "задание не задали - я его сам себе придумал", Вы же должны предложить критерии проверки результата при разных законах распределения случайных чисел.
В зависимости от условий задачи следует оценить результат неслучайности генерирования случайных чисел.
Подробнее (и гораздо увлекательнее) об этом написал Д.Кнут в "Искусство программирования для ЭВМ", т.2: "Получисленные алгоритмы", гл.3: "Случайные числа" (примерно 180 страниц).
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32934331
f2f
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
f2f
Гость
Сгенерировать N чисел удовлетворяющих распределению,
посчитать сумму и отнормировать
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32934550
Processor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
f2fСгенерировать N чисел удовлетворяющих распределению,
посчитать сумму и отнормироватьПряник, и без Кнута!
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32934700
kanalex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ProcessorПодробнее (и гораздо увлекательнее) об этом написал Д.Кнут в "Искусство программирования для ЭВМ", т.2: "Получисленные алгоритмы", гл.3: "Случайные числа" (примерно 180 страниц).

:)
Странное дело! Именно этим и занимался последние несколько часов...
Но, увы:( Уже порядком подзабыл математику, а потому изучение теории грозит затянуться на долгие дни и недели.:(

Поэтому предлагаю перевести разговор в практическую плоскость.
Рекомендации f2f немного более понятны, за исключением термина "отнормировать".
Объясните, пожалуйста, что имеется ввиду.

А пока набросал такой вот код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
Sub SmashToBits(A As Long, N As Integer, pr As Long)
'A - Число, которое надо разбить на части.
'N - Количество частей, на которое надо разбить число А
'Pr - процент отклонения от среднего для случайных чисел  0<Pr<100
Dim Sr, SrOst, Sum1, Ost, Max, Min As Single
Dim i As Integer
Dim ar() As Single
Dim res As String

    ReDim ar(N)
    Sr = A / N                'Среднее значение
    Max = Sr + Sr * pr /  100   'Максимальное отклонение от среднего
    Min = Sr - Sr * pr /  100   'Минимальное отклонение от среднего
    
    Randomize
    Sum1 =  0 
    'Формируем массив случайных чисел с заданным отклонением относительно Максимума
    For i =  0  To N -  1 
        ar(i) = Max -  2  * Rnd * pr /  100  * Sr
        Sum1 = Sum1 + ar(i)
    Next
    'Среднее число от остатка
    SrOst = (A - Sum1) / N
    
    Sum1 =  0 
    'Добавляем среднее от остатка к каждому элементу массива
    For i =  0  To N -  1 
        ar(i) = ar(i) + SrOst
        Sum1 = Sum1 + ar(i)
    Next
    
    'Контроллируем получившуюся сумму.
    'Если она не равна заданной, то разницу добавляем к случайному элементу массива.
    If Sum1 <> A Then
        Ost = A - Sum1
        i = (N -  1 ) * Rnd
        ar(i) = ar(i) + Ost
    End If
    
    Sum1 =  0 
    For i =  0  To N -  1 
        res = res & ar(i) & vbCrLf
        Sum1 = Sum1 + ar(i)
    Next
    Debug.Print res
    Debug.Print Sum1 & " " & Min & " " & Max
End Sub

Вообщем он дает достаточно близкие результаты к тому, что хотелось бы видеть...и для конкретной задачи вполне подойдет.

Но, все-таки, хотелось бы разобраться до конца с поставленной задачей:)
Можно ли подправить представленный код так, чтобы не вылетать (хоть и изредка) за пределы установленного диапазона?
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32934702
kanalex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тот же алгоритм реализованный на листе Excel в прикрепленном файле.
Так немного нагляднее выглядят результаты.
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32936116
Processor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kanalexтакой вот код... дает достаточно близкие результаты к тому, что хотелось бы видеть...и для конкретной задачи вполне подойдет.Если задача рАзовая - закройте глаза и примите результат к исполнению.
Если надеетесь работать и дальше со случайными числами, придётся всё же уделить несколько часов :) теории,
тряхнуть стариной и вспомнить математику :), чтобы остальным не было "мучительно больно" читать вопрос, что такое "отнормировать".
Неужели после чтения Кнута :) "в последние несколько часов" у вас не возникло ощущение увлекательности такого чтения?
А зря!
Тогда бы не было на листе Excel'а формул типа:
случ.число=ОКРУГЛ(СЛЧИС();2)
kanalexНо, все-таки, хотелось бы разобраться до конца с поставленной задачей:)"Хотелось бы...", "хочется" или "надо"?
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32947508
kanalex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что ж...
Задача решилась следующим образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
'Функция округляет числа до указанного количества знаков.
'Если Digits<0, то округление происходит до соотв. разряда целого числа
Public Function MyRound(ByVal N As Single, Optional Digits As Integer =  0 , _
                                     Optional sposob As Integer =  0 )
    'Округляем по правилам
    If sposob =  0  Then
        If Digits >=  0  Then
            'обычное округление десятичных разрядов после запятой
            MyRound = Round(N, Digits)
        Else
            'округдение до десятков, сотен ...
            For i = Digits +  1  To  0 
                N = N /  10 
            Next
            N = Round(N)
            For i = Digits +  1  To  0 
                N = N *  10 
            Next
            MyRound = N
        End If
    'округляем в большую сторону
    Else
        If Digits >=  0  Then
            'округление десятичных разрядов после запятой
            If N > Round(N, Digits) Then
                m =  1 
                For i =  0  To Digits -  1 
                    m = m /  10 
                Next
                MyRound = Round(N, Digits) + m
            Else
                MyRound = Round(N, Digits)
            End If
        Else
            'округдение до десятков, сотен ...
            For i = Digits +  1  To  0 
                N = N /  10 
            Next
            If N <> Int(N) Then
                N = Int(N) +  1 
            End If
            For i = Digits +  1  To  0 
                N = N *  10 
            Next
            MyRound = N
        End If
    End If
End Function

'-------------------------------------------------------------
'A - Число, которое надо разбить на части.
'N - Количество частей, на которое надо разбить число А
'Pr - процент отклонения от среднего для случайных чисел  0<Pr<100
'PlusSr - Абсолютное отклонение от среднего в плюс
'PlusSr - Абсолютное отклонение от среднего в минус
'  можно указать либо процентное отклонение, либо абсолютное в плюс и в минус,
'  если указано абсолютное, то процентное должно быть равно 0!
'Iteration - количество итераций для поиска решения.
Sub SmashToBits(A As Long, N As Integer, _
                ByRef Arr() As Single, _
                Optional pr As Long =  0 , _
                Optional PlusSr As Single =  0 , _
                Optional MinusSr As Single =  0 , _
                Optional Tochnost As Integer =  0 , _
                Optional Iteration As Integer =  100 )
Dim Sr, SrOst, Ost As Single
Dim i, j As Integer
Dim res As String
    
    On Error GoTo errhandler
 
    ReDim Arr(N)
    Sr = A / N                'Среднее значение
    If pr <>  0  Then
        Max = Sr + Sr * pr /  100   'Максимальное отклонение от среднего
        Min = Sr - Sr * pr /  100   'Минимальное отклонение от среднего
    Else
        Max = Sr + PlusSr         'Максимальное отклонение от среднего
        Min = Sr - MinusSr          'Минимальное отклонение от среднего
    End If
    
    Randomize
    j =  1 
    Do
        Sum1 = A
        For i =  1  To N -  1 
            Arr(i) = MyRound((Max - Min) * Rnd + Min, Tochnost)
            'Debug.Print Arr(i)
            Sum1 = Sum1 - Arr(i)
        Next
        Arr(N) = MyRound(Sum1, Tochnost)
        Sum1 = Sum1 - Arr(N)
        If ((Arr(N) < Max) And (Arr(N) > Min)) Then
            Exit Do
        End If
        j = j +  1 
    Loop Until j > Iteration
    If ((Arr(N) > Max) Or (Arr(N) < Min)) Then
        Err.Raise vbObjectError +  513 , "SmashToBits", _
        "Не удалось сформировать нужный массив за  " & j -  1  & " итераций!!!"
    End If
    
    'Sum1 = 0
    'res = ""
    'For i = 1 To N
    '    res = res & Arr(i) & vbCrLf
    '    Sum1 = Sum1 + Arr(i)
    'Next
    'Debug.Print res
    'Debug.Print Sum1 & " " & Min & " " & Max
    'Debug.Print "Количество потребовавшихся итераций = " & j
    
    Exit Sub
    
errhandler:
    MsgBox "Ошибка! " & Chr( 10 ) & Err.Description & Chr( 10 ) & " Номер ошибки " & Err.Number
End Sub
Результаты возвращает вполне корректные.
Конечно можно задать условия, при которых решение найдено не будет..., т.ч. будьте внимательны при вводе аргументов - особенно отклонений от среднего.
Процедура ведет себя особенно плохо, когда отклонения от среднего сильно отличаются друг от друга. Вообщем-то это и понятно.
Лично мне не очень нравится способ, которым задача решилась, но это субъективно. Не люблю я итерации:), т.ч. вопрос о возможном другом - более изящном решении остается открытым.

Всем спасибо!
Благодарности Professor - за исчерпывающие объяснения,
ну и Кнуту, конечно же.
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32948206
Processor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
KanalexБлагодарности Professor - за исчерпывающие объяснения,
ну и Кнуту, конечно же.1. Неверная последовательность в перечислении.
2. Ироничное Professor, присвоенное мне моими коллегами, как обычно - в неформальной обстановке,
довольно быстро трансформировалось ими же в уважительное Processor более 20 лет назад.
Этот ник и использую в конференциях (то-бишь "форумах").
Не обижаюсь :-)
3. Любое число можно рассматривать как случайное только в совокупности с другими.
"Степень" случайности (в смысле непохожести) возрастает с увеличением разрядной сетки в представлении числа,
если числа выдаёт программный ДСЧ.
(и об этом так увлекательно рассказывает Д.Кнут).
Из этих позиций я критиковал Вашу строчку "случ.число=ОКРУГЛ(СЛЧИС();2)".
Округление до заданной точности надо производить на заключительном этапе, если это диктуется требованиями к результатам.
Например, если Вы должны получить рубли с копейками.
Но тут без итераций не обойтись - бухгалтерия обязана получить сумму с точностью "до копейки"...
...
Рейтинг: 0 / 0
Excel: Разбить число на N случайных составляющих...
    #32950278
kanalex
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Processor
2. Ироничное Professor, присвоенное мне моими коллегами, как обычно - в неформальной обстановке,
довольно быстро трансформировалось ими же в уважительное Processor более 20 лет назад.
Этот ник и использую в конференциях (то-бишь "форумах").
Не обижаюсь :-)
Значит попал в 10-ку:)
Я присоединюсь к Вашим коллегам - отныне буду обращаться к Вам Processor.

Processor
3. Любое число можно рассматривать как случайное только в совокупности с другими.
"Степень" случайности (в смысле непохожести) возрастает с увеличением разрядной сетки в представлении числа,
если числа выдаёт программный ДСЧ.
(и об этом так увлекательно рассказывает Д.Кнут).
Из этих позиций я критиковал Вашу строчку "случ.число=ОКРУГЛ(СЛЧИС();2)".
Округление до заданной точности надо производить на заключительном этапе, если это диктуется требованиями к результатам.
Например, если Вы должны получить рубли с копейками.
Но тут без итераций не обойтись - бухгалтерия обязана получить сумму с точностью "до копейки"...
Вообщем согласен с критикой. Единственным оправданием мне может служить то, что в том примере я имел ввиду целое число процентов, которое и использовал в дальнейших вычислениях....
Признаюсь - был не прав:)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Excel: Разбить число на N случайных составляющих...
    #34327412
Фотография Jojo
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
спасибо автору за функцию округления, проходилась \m/

Scio me nihil scire

<<Jojo®>>
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / Excel: Разбить число на N случайных составляющих...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]