Сила C# ListBox для обновления элементов

1141 На точность вы уже получили хорошие ответы. Для самой задачи вы можете быть быстрее, вложив некоторое исчисление.

  • Во-первых, из границ синуса вы знаете, что любое решение должно быть в интервале [-abs(a),abs(a)]. Если abs(a)\le 1, то единственный корень в [-1,1] - это x=0

  • Помимо интервала, содержащего ноль, вы также знаете, что в любом из интервалов есть ровно один корень корни из cos(x)=1/a, которые являются экстремумами из a*sin(x)-x. Установите phi=arccos(1/a) in [0,pi], тогда этими корнями являются -phi+2*k*pi и phi+2*k*pi.

  • Интервал для k=0 может содержать 3 корня, если 1<a<0.5*pi. Для положительного корня известно x/a=sin(x)>x-x^3/6, так что x^2>6-6/a.

  • И, наконец, проблема симметрична, если x является корнем, то же самое происходит с -x, поэтому все, что вам нужно сделать, это найти положительные корни.

Итак, чтобы вычислить корни,

  • Запустите корневой список с корнем 0.
  • В случае abs(a)<=1 дальнейших корней нет, возвратите. Можно также использовать -pi/2<=a<=1.
  • в случае 1<a<pi/2, применить выбранный метод брекетинга к интервалу [sqrt(6-6/a), pi/2], добавить корень в список и вернуться.
  • В остальных случаях, когда abs(a)>=0.5*pi:

    • Вычислить phi=arccos(1/a).
    • Затем для любого натурального числа k примените метод брекетинга к интервалам [2 * (k-1) * pi + phi, 2 * k * pi-phi] и [2 * k * pi- phi, 2 * k * pi-phi, так что (k-0.5)*pi < abs(a) [(k-0.5)*pi, (k+0.5)*pi] до тех пор, пока нижняя граница интервала меньше, чем abs(a) и функция имеет изменение знака в течение интервала.
    • Добавить найденный корень в список. Вернитесь со списком после окончания цикла.

let a=10;

function f(x) { return x - a * Math.sin(x); }

findRoots();

//-------------------------------------------------

function findRoots() {
    log.innerHTML = `<p>roots for parameter a=${a}`;
    rootList.innerHTML = "<tr><th>root <i>x</i></th><th><i>x-a*sin(x)</i></th><th>numSteps</th></tr>";
    rootList.innerHTML += "<tr><td>0.0<td>0.0<td>0</tr>";

    if( Math.abs(a)<=1) return;

    if( (1.0<a) && (a < 0.5*Math.PI) ) {
        illinois(Math.sqrt(6-6/a), 0.5*Math.PI);
        return;
    }

    const phi = Math.acos(1.0/a);
    log.innerHTML += `phi=${phi}<br>`;
    let right = 2*Math.PI-phi;
    for (let k=1; right<Math.abs(a); k++) { 
        let left = right;
        right = (k+2)*Math.PI + ((0==k%2)?(-phi):(phi-Math.PI));
        illinois(left, right);
    }
}

function illinois(a, b) {
  log.innerHTML += `<p>regula falsi variant illinois called for interval [a,b]=[${a}, ${b}]`;
  let fa = f(a);
  let fb = f(b);
  let numSteps=2;
  log.innerHTML += ` values f(a)=${fa}, f(b)=${fb}</p>`;

  if (fa*fb > 0) return;

  if (Math.abs(fa) < Math.abs(fb)) { var h=a; a=b; b=h; h=fa; fa=fb; fb=h;}
  
  while(Math.abs(b-a) > 1e-15*Math.abs(b)) {
    let c = b - fb*(b-a)/(fb-fa);
    let fc = f(c); numSteps++;
    log.innerHTML += `step ${numSteps}: midpoint c=${c}, f(c)=${fc}<br>`;

    if ( fa*fc < 0 ) {
      fa *= 0.5;
    } else {
      a = b; fa = fb;
    }
    b = c; fb = fc;
  }
  rootList.innerHTML += `<tr><td>${b}<td>${fb}<td>${numSteps}</tr>`;
}

aInput.addEventListener('change', () => {
  let a_new = Number.parseFloat(aInput.value);
  if( isNaN(a_new) ) {
      alert('Not a number '+aInput.value);
  } else if(a!=a_new) {
     a = a_new;
     findRoots();
  }
});
<p>Factor <i>a</i>: <input id="aInput" value="10" /></p>
<h3>Root list</h3>
<table id="rootList" border = 1>
</table>
<h3>Computation log</h3>
<div id="log"/>

6
задан mafu 6 February 2009 в 08:22
поделиться

2 ответа

К сожалению, привязка данных в ListView не поддерживает регулярный (объект) события уведомления об изменении (FooChanged / INotifyPropertyChanged). Однако, если Вы знаете об изменении, можно заставить список снова переплетать себя. Так как Вы разделяете на подклассы, можно звонить:

this.RefreshItems();

или для единственного объекта:

this.RefreshItem(index);

Иначе, так как это не общедоступно, можно моделировать его путем изменения DisplayMember:

lb.DisplayMember = "";
lb.DisplayMember = "Bar";

Немного hacky, возможно, но это работает и поддерживает текущий выбор и т.д. (в отличие от очистки DataSource).

16
ответ дан 8 December 2019 в 13:50
поделиться

Почему Вы вручную не обновляете текст рассматриваемого объекта? Вы могли бы также рассмотреть развертывание Вашего собственного механизма привязки данных для ListBox. И проверьте ObjectListView, чтобы видеть, имеет ли это какую-либо справку.

1
ответ дан 8 December 2019 в 13:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: