Это слово, кажется, используется во многих контекстах. Лучшее, что я могу понять, это то, что они означают переменную, которая не может измениться. Разве не для этого нужны константы / финалы (черт возьми, Java!)?
Инвариант - это математическая концепция, которая больше подходит к теоретической части спектра информатики.





Это условие, которое, как вы знаете, всегда будет истинным в определенном месте вашей логики и которое вы можете проверить при отладке, чтобы выяснить, что пошло не так.
Я обычно рассматриваю их больше с точки зрения алгоритмов или структур.
Например, у вас может быть инвариант цикла, который можно утверждать - всегда истинно в начале или в конце каждой итерации. То есть, если ваш цикл должен был обрабатывать коллекцию объектов из одного стека в другой, вы могли бы сказать, что | stack1 | + | stack2 | = c, вверху или внизу цикла.
Если проверка инварианта не удалась, это будет означать, что что-то пошло не так. В этом примере это может означать, что вы забыли поместить обработанный элемент в последний стек и т. д.
Магия википедии: Инвариант (информатика)
In computer science, a predicate that, if true, will remain true throughout a specific sequence of operations, is called (an) invariant to that sequence.
Ссылки? Технический жаргон? ЧИТАЕТ? WTF? ;) Если серьезно, то хорошая ссылка, но было бы неплохо немного подытожить.
Инвариант более «концептуален», чем переменная. В общем, это свойство состояния программы, которое всегда истинно. Говорят, что функция или метод, обеспечивающий выполнение инварианта, поддерживает его.
Например, двоичное дерево поиска может иметь инвариант, что для каждого узла ключ левого потомка узла меньше, чем собственный ключ узла. Правильно написанная функция вставки для этого дерева будет поддерживать этот инвариант.
Как вы понимаете, это не то, что можно хранить в переменной: это скорее оператор о программы. Выяснив, какие инварианты должна поддерживать ваша программа, а затем проверив свой код, чтобы убедиться, что он действительно поддерживает эти инварианты, вы можете избежать логических ошибок в своем коде.
Этот отличный пример был бы лучше, если бы он включал ответ cero со ссылкой на википедию.
Возраст родителей больше возраста их биологических детей. Окружающий контекст изменится, но инвариант никогда не изменится. Например, это может быть семья Смитов, у которой двое детей. Или это могло быть у других видов любого млекопитающего. Контекст меняется, но инвариант не меняется.
"... свойство программного состояния, которое всегда истинно ..." - @jacob baskin - хорошо написано, и спасибо за это.
«... свойство состояния программы, которое всегда истинно ...» - я согласен, что это хорошо написано, но это может вводить в заблуждение. Сначала я понял, что это логическое значение true, но я почти уверен, что это означает «... всегда константа» (но, возможно, это просто потому, что английский не мой родной язык)
Я думаю, стоит упомянуть, что инварианты помогают вам написать индуктивное доказательство, что ваша функция или программа верны. Могут быть и другие применения, но только это чрезвычайно полезно.
Исходя из того, что это такое, инварианты весьма полезны при написании чистого кода, поскольку концептуальное представление о том, какие инварианты должны присутствовать в вашем коде в, позволяет вам легко решить, как организовать свой код для достижения этих целей. Как уже упоминалось ранее, они также полезны при отладке, поскольку проверка того, поддерживается ли инвариант, часто является хорошим способом увидеть, действительно ли какая-либо манипуляция, которую вы пытаетесь выполнить, выполняет то, что вы хотите.
Что-то, что не меняется в блоке кода
Инвариант ADT определяет отношения среди полей данных (переменные экземпляра) это всегда должно быть правдой до и после выполнение любого метода экземпляра.
Как говорится в этой строке:
In computer science, a predicate that, if true, will remain true throughout a specific sequence of operations, is called (an) invariant to that sequence.
Чтобы лучше понять эту надежду, этот пример на C++ помогает.
Рассмотрим сценарий, в котором вам нужно получить некоторые значения и получить их общее количество в переменной count и добавить их в переменную sum.
// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades
Код для вышеперечисленного будет примерно таким:
int count=0;
double sum=0,x=0;
while (cin >> x) {
++count;
sum+=x;
}
Что делает приведенный выше код?
1) Считывает ввод от cin и помещает их в x
2) После одного успешного чтения увеличьте count и sum = sum + x
3) Повторяйте 1-2, пока чтение не остановится (например, ctrl + D)
Инвариант должен быть True ВСЕГДА. Итак, сначала вы начинаете свой код только с этого
while(cin>>x){
}
Этот цикл считывает данные со стандартного ввода и сохраняет их в x. Ну и хорошо. Но инвариантный становится ложным, потому что первая часть нашего инвариантный не соблюдалась (или оставалась истинной).
// we have read count grades so far, and
Простой! счетчик приращения.
Так что ++count; подойдет !. Теперь наш код выглядит примерно так:
while(cin>>x){
++count;
}
Даже сейчас наш инвариантный (концепция, которая должна быть TRUE) является False, потому что теперь мы не удовлетворили вторую часть инварианта наш.
// sum is the sum of the first count grades
Так что же теперь делать?
Добавьте x к sum и сохраните его в sum (sum+=x) и в следующий раз
cin>>x прочитает новое значение в x.
Теперь наш код выглядит примерно так:
while(cin>>x){
++count;
sum+=x;
}
// invariant:
// we have read count grades so far, and
// sum is the sum of the first count grades
код:
while(cin>>x){
++count;
sum+=x;
}
Ах !. Теперь инвариант цикла - True всегда, и код работает нормально.
Вышеупомянутый пример был взяты и изменены из в книге Ускоренный C++ Эндрю-Коенинга и Барбары-Э.
Обычно это величина, которая не меняется при выполнении определенных математических операций. пример - это скаляр, который не изменяется при поворотах. Например, при магнитно-резонансной томографии полезно характеризовать свойство ткани с помощью инварианта вращения, потому что тогда его оценка в идеале не зависит от ориентации тела в сканере.
В книге Параллелизм Java на практике есть отличный пример инварианта и его значение.
Хотя этот пример ориентирован на Java, он описывает некоторый код, который отвечает за вычисление коэффициентов предоставленного целого числа. В примере кода предпринимается попытка кэширования последнего предоставленного числа и факторов, которые были рассчитаны для повышения производительности. В этом сценарии есть инвариант, который не был учтен в примере кода, что сделало код восприимчивым к условиям гонки в параллельном сценарии.
Все ответы здесь отличные, но я чувствовал, что могу пролить больше света на этот вопрос:
Инвариант с языковой точки зрения означает то, что никогда не меняется. Хотя эта концепция на самом деле исходит из математики, это один из популярных методов доказательства в сочетании с индукцией.
Вот как проходит доказательство: если вы можете найти инвариант, который находится в начальном состоянии, и что этот инвариант сохраняется независимо от любого [законного] преобразования, примененного к состоянию, тогда вы можете доказать, что если определенное состояние не имеет этого инвариантно, то это никогда не может произойти, независимо от того, какая последовательность преобразований применяется к начальному состоянию.
Предыдущий способ мышления (опять же в сочетании с индукцией) позволяет предиктировать логику компьютерного программного обеспечения. Это особенно важно, когда выполнение происходит в циклах, в которых инвариант может использоваться, чтобы доказать, что определенный цикл даст определенный результат или что он никогда не изменит состояние программы определенным образом.
Когда инвариант используется для предиката логики цикла, он называется инвариант цикла. Его можно использовать вне циклов, но для циклов это действительно важно, потому что у вас часто есть много возможностей или бесконечное количество возможностей.
Обратите внимание, что я использую слово «предикат» для логики компьютерного программного обеспечения, а не для доказательства. И это потому, что, хотя в математике инвариантный может использоваться в качестве доказательства, он никогда не может доказать, что компьютерное программное обеспечение при запуске даст то, что ожидается, из-за того, что программное обеспечение выполняется поверх многих абстракций, что никогда не может быть доказано. что они дадут то, что ожидается (подумайте, например, об аппаратной абстракции).
Наконец, хотя теоретическое и строгое предсказание логики программного обеспечения важно только для критически важных приложений, таких как медицинские и военные. Инвариант по-прежнему может использоваться для помощи обычному программисту при отладке. Его можно использовать, чтобы узнать, где в определенном месте. Программа потерпела неудачу, потому что она не смогла сохранить определенный инвариант - многие из нас все равно используют ее, даже не задумываясь об этом.
Этот ответ предназначен для моего 5-летнего ребенка. Не думайте об инварианте как о постоянном или фиксированном числовом значении. Но может быть. Однако это еще не все.
Скорее, инвариант - это что-то вроде фиксированного отношения между различными объектами. Например, ваш возраст всегда будет меньше, чем у ваших биологических родителей. И ваш возраст, и возраст ваших родителей со временем меняются, но отношения, о которых я упоминал выше, остаются неизменными.
Инвариант также может быть числовой константой. Например, значение pi - это неизменное соотношение длины окружности к ее диаметру. Независимо от того, насколько большой или маленький круг, это соотношение всегда будет pi.
Class Invariant - это условие, которое всегда должно выполняться до и после вызова соответствующей функции.
Например, у сбалансированного дерева есть Invariant, который называется isBalanced. Когда вы изменяете свое дерево с помощью некоторых методов (например, addNode, removeNode ...) - isBalanced всегда должен быть истинным до и после изменения дерева.
Может, надо было назвать это безвариантным?