Всем привет! Ноги здесь Задача проста: Сколько цветов RGB будет в произвольно задаваемом диапазоне (к примеру 500-700), если этот диапазон получен сложением R+G+B? Как вывести результат математически?
Полный диапазон 0(0+0+0) - 765(255+255+255) Сначала я сделал неверное предположение, что это 200^3 = 8 млн. Далее, просто набросал код:
Код
Sub run()
Debug.Print count(500, 700) '0-765
End Sub
Function count(iMin As Long, iMax As Long) As Long
Dim R As Long, G As Long, B As Long
For R = 0 To 255 Step 1
For G = 0 To 255 Step 1
For B = 0 To 255 Step 1
If R + G + B >= iMin And R + G + B <= iMax Then count = count + 1
Next
Next
Next
End Function
Вышло - 3 123 751 цветов.
Понял, что это комбинаторика и набросал еще код, раскладывающий количество цветов на каждую единицу данного диапазона (0-765).
Код
Sub run()
Dim i As Long
For i = 0 To 765
Cells(i + 1, 1) = count(i, i)
Next
End Sub
Function count(iMin As Long, iMax As Long) As Long
Dim R As Long, G As Long, B As Long
For R = 0 To 255 Step 1
For G = 0 To 255 Step 1
For B = 0 To 255 Step 1
If R + G + B >= iMin And R + G + B <= iMax Then count = count + 1
Next
Next
Next
End Function
Результат в файле. Какой математической функцией можно получить данный результат?
P.S. Все знают, но здесь оставлю, что принимает Color и как работает функция RGB() Excel.Color = RGB(R*256^0+G*256^1+B*256^2), диапазон 0-(256^3-1)
Evgenyy, здорово! Боюсь даже спросить, как эти формулы были выведены?) Есть подозрение, что можно вывести единую формулу для всего диапазона. Ведь диапазон зеркальный, относительно своей середины.
Эта задача имеет практические корни. Для генерации приятных цветов, для раскраски групп дубликатов, придумал такой алгоритм. В диапазоне до 400-500 цвета темные или химические, редко нормальные попадаются, выделяемый текст плохо видно, далее в диапазоне 500-700 светлее и как по-мне норм, далее 700-765 совсем светлые, на любителя. Выходит у меня есть 3 млн цветов для использования из 16 млн.
Вывел полиноминальную линию тренда (6й степени), ввел предложенную формулу и не получил нужный результат (данные не сошлись с линией тренда). Что сделал не так?
bedvit написал: полиноминальную линию тренда (6й степени)
Я думаю 6 степень - не лучший вариант. Можно попробовать 4-ю или 8-ю с положительным коэффициентом при степени. Должна быть кривая, ветви которой направленны вверх, а в середине выпуклость (т.е. иметь 2 минимума, 1 максимум и 4 точки перегиба).
Evgenyy, у меня Excel максимум дает 6-ю, вы сможете сделать полиноминальную линию тренда 8й степени? 4й степени пробовал, вообще мимо. Плюс остается вопрос почему предложенная Excel формула не работает?
БМВ, работает с погрешность 15% это нормально? Причем величина достоверности аппроксимации 0.9994, т.е близка к единице. Это впрочем видно по красной линии тренда, которая почти совпадает с данными. Для чего - просто хочу посчитать математически, а не макросом количество цветов. Если бы я не умел бы писать программы, как бы я посчитал?
Как-то извращался с цветами (одному студенту дали задание, как я понял, заполнить две таблицы 100х100 рандомными числами от 0 до 1000 и ячейки дубликатов выделить разными цветами), сделал на темный фон - светлый шрифт и наоборот. Получилось красиво, но бесполезно.
Скрытый текст
Код
Sub Task2()
Application.ScreenUpdating = False
Dim key As Long, item As Long
Dim objDic As Dictionary 'Раннее связывание - Microsoft Scripting Runtime
Dim aRange As Range, bRange As Range
Dim dMax As Long, t As Single
Dim c As Long, k1 As Long, k2 As Long
Dim i As Long, i1 As Long, i2 As Long
Dim a(1 To 100, 1 To 100) As Long
Dim b(1 To 100, 1 To 100) As Long
If objDic Is Nothing Then Set objDic = New Dictionary
Set objDic = CreateObject("Scripting.Dictionary")
Set aRange = Range("A1:CV100")
Set bRange = Range("CX1:GS100")
dMax = 16777215
On Error Resume Next
Do While objDic.Count < 1001
key = Int((dMax + 1) * Rnd)
objDic.Add key, item
item = item + 1
Loop
On Error GoTo 0
dMax = 1000
For c = 1 To 100
For i = 1 To 100
i1 = Int((dMax + 1) * Rnd)
i2 = Int((dMax + 1) * Rnd)
a(i, c) = i1
b(i, c) = i2
k1 = objDic.Keys(i1)
k2 = objDic.Keys(i2)
Cells(i, c).Interior.Color = k1
Cells(i, c + 101).Interior.Color = k2
If DarkLight(k1) Then
Cells(i, c).Font.ThemeColor = xlThemeColorLight1
Else
Cells(i, c).Font.ThemeColor = xlThemeColorDark1
End If
If DarkLight(k2) Then
Cells(i, c + 101).Font.ThemeColor = xlThemeColorLight1
Else
Cells(i, c + 101).Font.ThemeColor = xlThemeColorDark1
End If
Next i
Next c
aRange = a: bRange = b: aRange.RowHeight = 15
aRange.ColumnWidth = 4: bRange.ColumnWidth = 4
Application.ScreenUpdating = True
End Sub
Function DarkLight(k) As Boolean
Dim a()
a = Array(k \ 256 ^ 0 And 255, k \ 256 ^ 1 And 255, k \ 256 ^ 2 And 255)
If (1 - (0.299 * a(0) + 0.587 * a(1) + 0.114 * a(2)) / 255 < 0.5) Then
DarkLight = True
Else
DarkLight = False
End If
End Function
bedvit написал: работает с погрешность 15% это нормально?
Виталий, ну задача то линии тренда не формулу построить, а кривую, она близка - факт, а то что значения полинома не совпади - так формула для справки дана :-)
Судя по коду и результату, мы считаем количества вариантов получения указаннго числа 0,1,2… путем суммирования чисел от одного до 255 из трех групп. Даже если комбинаторику задействовать то там будут факториалы и потребуются циклы.
БМВ написал: то там будут факториалы и потребуются циклы.
Насчёт факториалов не знаю, а вот то что задача похожа на задачу о линейном раскрое - это да. Пусть есть доски от 500 до 700. Нужные детали 0 до 255. Нужно определить сколько раз можно используя ровно три детали, можно разделить доски на ровно на три детали.
в том и дело, что они должны совпасть не с исходными, а с самой линией тренда, а они не совпадают! Андрей VG, Андрей привет! Звучит неплохо, продолжай !
Evgenyy, эта функция уже есть, если посмотреть ссылку в начале темы откуда ноги растут Выглядит она так
Код
Function Generate_nice_color() As Long
Dim R As Long, G As Long, B As Long
Do
Randomize
R = Int(Rnd * 256)
G = Int(Rnd * 256)
B = Int(Rnd * 256)
Loop Until R + G + B > 500 And R + G + B < 700
Generate_nice_color = RGB(R, G, B)
End Function
она рандомная, и спектр цветов более богат, чем цвета которые генерируются рядом друг с другом.
Добрый день, коллеги! Математика здесь не может быть сложной.
Пусть S(N) - число целочисленных решений уравнения a+b=N, где 0<=a,b<=255. Понятно из ограничений, что: S(N)=N+1 при 0<=N<=255 S(N)=511-N при 256<=N<=510
Кусочно-линейная функция из двух частей.
Пусть теперь T(N) - число целочисленных решений для трех слагаемых с указанными ограничениями. Тогда, например, при 0<=N<=255 мы должны просуммировать S(k) от k=0 до N. В итоге, как и написал коллега в сообщениях #2 и #5, получаем многочлен 2-й степени. Аналогично для других интервалов. Такие штуки называются сплайнами.
Если нас интересует число целочисленных решений неравенства N1<=a+b+c<=N2, где a,b,c лежат в указанных интервалах, то после суммирования T(N) мы для каждого подинтервала получим многочлены 3-й степени.
aequit, раннее связывание отключил, посмотрите рис., Возможно причина в разных свойствах словарей, я не пользовался ранним связыванием библ. Microsoft Scripting Runtime. Evgenyy, в любом случае спасибо за участие Андрей Лящук, сильно, интересно, какой либо вариант даёт 100% попадание?) Михаил, Андрей задача не критичная, на интерес ) Решение простым перебором быстро решается, даже библу писать не надо:) Но я всегда думал математика и алгоритм сильнее тупой вычислительной мощи. Здесь видимо наоборот.
bedvit написал: Но я всегда думал математика и алгоритм сильнее тупой вычислительной мощи. Здесь видимо наоборот.
не всегда. Вот пример , когда все есть , и уравнение и … но реально вспоминать как найти угол не очень получилось, за последние 30 лет позабылось все :-) .
Цитата
sokol92 написал: Математика здесь не может быть сложной.
пойду курну, а то чую выходные на смарку пойду. Такое в пятницу вечером завернул , а