Функция за намиране на записи с еднаква максимална стойност във вектор

В моя проект имам нужда от функция, която връща индекса на най-големия елемент от даден вектор. Точно като max. За повече от един запис с една и съща максимална стойност (което се случва често) функцията трябва да избере един на случаен принцип. За разлика от max.

Функцията е подфункция във функционален блок MATLAB в Simulink. И целият модел Simulink е компилиран.

Основната ми идея беше:

function ind = findOpt(vector)
index_max = find(vector == max(vector));
random = randi([1,length(index_max)],1);
ind = index_max(random);
end

Но имам проблеми със сравнението в find и с randi. Разбрах за безопасно сравнение тук: Проблем с използването на функцията за намиране в MATLAB. Също така намерих начин да заменя randi([1,imax],1): Имплементирайте 'randi' с помощта на 'rand' в MATLAB.

Моят код сега изглежда така:

function ind = findOpt(vector)
tolerance = 0.00001;
index_max = find(abs(vector - max(vector)) < tolerance);
random = ceil(length(index_max)*rand(1));
ind = index_max(random);
end

Все още не работи. Разбирам, че дължината на index_max е неясна и създава проблеми. Но не мога да измисля начин да го знам преди. Някакви идеи как да се реши това?

Освен това съм шокиран, че ceil не работи, когато кодът се изпълни?? В режим на отстраняване на грешки няма видима промяна във входа.

Мислех да създам масив като: index_max = abs(vector - max(vector)) < tolerance; Но не съм сигурен как това може да помогне. Освен това не решава проблема ми с произволния избор. Надяваме се, че някой има повече идеи или поне може да ми даде някои съвети!

Използвам MATLAB R2012b (32-битов) на Windows7-64-битов компютър с компилатор Lcc-win32 C 2.4.1.

Редактиране: Векторът обикновено е с размер 5x1 и съдържа стойности между -2000 и нула, които са от тип double, напр. vector = [-1000 -1200 -1000 -1100 -1550]'. Но мисля, че такава проста функция трябва да работи с всякакъв вид входен вектор.

Обаждането на length(index_max) причинява системна грешка в MATLAB и ме принуждава да го изключа. Предполагам, че това се дължи на странното връщане, което получавам от find. За вектор с всички същите стойности връщането от find е нещо като [1.000 2.000 1.000 2.000 0.000]', което изобщо няма смисъл за мен.


person FxH    schedule 15.01.2014    source източник
comment
какво не работи? Опитахте кода си в matlab и изглежда добре?   -  person stijn    schedule 15.01.2014
comment
В MATLAB работи добре и за мен. Но изпълнението на модела Simulink причинява грешка по време на изпълнение, казвайки: Очаквана е целочислена стойност, открита е произволна нецелочислена променлива със стойност 4.07362. За реда с: ind=index_max(random);   -  person FxH    schedule 15.01.2014
comment
хмм Това е интересно..   -  person stijn    schedule 15.01.2014
comment
внедрите ceil сами.   -  person Autonomous    schedule 15.01.2014
comment
бихте ли публикували своя вектор? Предполагам, че има много прости решения, използващи find и randi, но предполагам, че не искате да ги използвате   -  person Autonomous    schedule 15.01.2014
comment
Поставете random = length(index_max)*rand(1) и random = ceil(random) на последователни редове, без точка и запетая. Какъв е резултатът от тези два реда? Също така поставете which ceil във функцията, след реда, извикващ ceil, и ни дайте изхода и от този ред.   -  person user664303    schedule 15.01.2014
comment
Поставянето на which ceil ми дава грешка на кодера, заявяваща: Функцията „which“ не се поддържа за генериране на coed. [...]. И ceil(x) все още връща x.   -  person FxH    schedule 15.01.2014
comment
Ако отворите нов MATLAB и извикате findOpt(rand(100, 1)), работи ли? Ако е така, предполагам, че кодът, от който обикновено извиквате findOpt(), претоварва ceil(); трябва да намериш къде.   -  person user664303    schedule 16.01.2014
comment
Съхраних findOpt() в M-файл и направих както казахте. Работи перфектно, дори и за моята оригинална реализация. Но все пак във функционален блок MATLAB в Simulink няма да работи. Не си мислете, че претоварвам ceil. Може ли да е проблем с компилатора? Утре ще имам шанса да го пробвам на друг компютър. Да видим какво ще стане там...   -  person FxH    schedule 16.01.2014


Отговори (2)


Наистина претоварвах, точно както предложи user664303! Тъй като не мога да използвам обекти в моя проект, исках функция, която се държи подобно, затова написах:

function varargout = table(mode, varargin)
persistent table;

if isempty(table) && ~strcmp(mode,'writeTable')
     error(...)
end

switch mode
     case 'getValue'
        ...
     case 'writeTable'
        table = ...
     ...
end
end

Исках да избегна предаването на измеренията за таблицата при всяко извикване и реших, че ще бъде достатъчно, ако първото извикване инициализира таблицата с mode='writeTable'. Изглежда, че това е причинило проблема ми. Няма проблеми след смяна на:

if isempty(table)
     table = zeros(dim1,dim2,...)
end
person FxH    schedule 18.01.2014

person    schedule
comment
Опитах го, но все още получавам грешка по време на изпълнение за ceil(rand(1)*end) По някакъв начин ceil не прави това, което трябва да прави, и просто преминава през rand(1)*end. - person FxH; 15.01.2014
comment
Какъв е резултатът от which ceil? Моят е built-in (C:\Program Files\MATLAB\R2013b\toolbox\matlab\elfun\@double\ceil) % double method. - person user664303; 15.01.2014