Причина в том, что в программе выполняется неопределенное поведение. Проблема заключается в порядке оценки, потому что не существует точек последовательности, требуемых согласно стандарту C ++ 98 (никакие операции не секвенированы до или после другого в соответствии с терминологией C ++ 11).
Однако, если вы
#include
int main(int argc, char ** argv)
{
int i = 0;
i = i++ + ++i;
printf("%d\n", i); // 2
i = 1;
i = (i++);
printf("%d\n", i); //1
volatile int u = 0;
u = u++ + ++u;
printf("%d\n", u); // 2
u = 1;
u = (u++);
printf("%d\n", u); //1
register int v = 0;
v = v++ + ++v;
printf("%d\n", v); //2
} Как работает GCC? он оценивает подвыражения в порядке слева направо для правой стороны (RHS), затем присваивает значение левой стороне (LHS). Именно так ведут себя Java и C # и определяют их стандарты. (Да, эквивалентное программное обеспечение на Java и C # определило поведение). Он оценивает каждое вспомогательное выражение один за другим в Заявлении RHS в порядке слева направо; для каждого подвыражения: сначала выполняется оценка ++ c (pre-increment), затем значение c используется для операции, затем приращение post c ++).
в соответствии с GCC C ++: Операторы
В GCC C ++ приоритет операторов контролирует порядок, в котором отдельные операторы оцениваются
blockquote>эквивалентный код в определенном поведении C ++, как понимает GCC:
#include
int main(int argc, char ** argv) { int i = 0; //i = i++ + ++i; int r; r=i; i++; ++i; r+=i; i=r; printf("%d\n", i); // 2 i = 1; //i = (i++); r=i; i++; i=r; printf("%d\n", i); // 1 volatile int u = 0; //u = u++ + ++u; r=u; u++; ++u; r+=u; u=r; printf("%d\n", u); // 2 u = 1; //u = (u++); r=u; u++; u=r; printf("%d\n", u); // 1 register int v = 0; //v = v++ + ++v; r=v; v++; ++v; r+=v; v=r; printf("%d\n", v); //2 } Затем переходим к Visual Studio . Visual Studio 2015 вы получаете:
#include
int main(int argc, char ** argv) { int i = 0; i = i++ + ++i; printf("%d\n", i); // 3 i = 1; i = (i++); printf("%d\n", i); // 2 volatile int u = 0; u = u++ + ++u; printf("%d\n", u); // 3 u = 1; u = (u++); printf("%d\n", u); // 2 register int v = 0; v = v++ + ++v; printf("%d\n", v); // 3 } Как работает визуальная студия, она использует другой подход, оценивает все выражения предварительного приращения в первом проходе, затем использует значения переменных в операциях во втором проходе, назначать из RHS на LHS в третьем проходе, затем, наконец, пропустить, он оценивает все выражения после инкремента за один проход.
Таким образом, эквивалент в определенном поведении C ++, как Visual C ++, понимает:
#include
int main(int argc, char ** argv) { int r; int i = 0; //i = i++ + ++i; ++i; r = i + i; i = r; i++; printf("%d\n", i); // 3 i = 1; //i = (i++); r = i; i = r; i++; printf("%d\n", i); // 2 volatile int u = 0; //u = u++ + ++u; ++u; r = u + u; u = r; u++; printf("%d\n", u); // 3 u = 1; //u = (u++); r = u; u = r; u++; printf("%d\n", u); // 2 register int v = 0; //v = v++ + ++v; ++v; r = v + v; v = r; v++; printf("%d\n", v); // 3 } как документация Visual Studio в Приоритет и порядок оценки :
Если несколько операторов отображаются вместе, они имеют одинаковый приоритет и оцениваются в соответствии со своей ассоциативностью. Операторы в таблице описаны в разделах, начинающихся с операторов Postfix.
blockquote>
Ну, n-й корень из x
на самом деле x^(1/n)
, поэтому вы можете сделать 9**(1/2.0)
, чтобы найти, например, 2-й корень из 9. В общем случае, чтобы найти n-й корень из x, просто выполните:
x**(1/float(n))
Вы также можете сделать 1.0/n
вместо 1/float(n)
. Это требуется, чтобы результат был float
, а не int
.
Если вы предпочитаете применять эту операцию функционально, а не с помощью инфиксного оператора (символ **
), вы можете передать базу и экспоненту в качестве аргументов функции pow
:
In [23]: (9**(0.5)) == pow(9, 0.5)
Out[23]: True
Я также увлекаюсь поиском новых применений для этого взлома Infix в Python , хотя это скорее развлечение, чем сверхмощное решение. Но вы могли бы сделать свой собственный персональный символ для этого, выполнив следующее:
class Infix:
def __init__(self, function):
self.function = function
def __ror__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __or__(self, other):
return self.function(other)
def __rlshift__(self, other):
return Infix(lambda x, self=self, other=other: self.function(other, x))
def __rshift__(self, other):
return self.function(other)
def __call__(self, value1, value2):
return self.function(value1, value2)
root_of = Infix(lambda x,y: y**(1.0/x))
print 2 |root_of| 9
3.0
В основном sqrt (9) эквивалентен 9 ^ .5
>>>9**.5
3.0
Есть. Это просто **
=)
Любой n-й корень является возведением в степень по 1/n
, поэтому, чтобы получить квадратный корень из 9, вы используете 9**(1/2)
(или 9**0.5
) для получения корня куба , вы используете 9 ** (1/3)
(который мы не можем записать с более простой дробью), и чтобы получить n-й корень, 9 ** (1/n)
.
Также обратите внимание, что с Python 3 добавление периодов к целым числам сделать их поплавком больше не нужно. Высказывание 1/3
работает так, как вы его ожидали, давая 0.333...
как результат, а не нуль. Для устаревших версий Python вам нужно будет запомнить этот период (но также критически удивляйтесь, почему вы используете устаревшую версию языка программирования)
Также: x**(n**-1)
, который является тем же, но короче x**(1/float(n))
Вы должны сделать
16**(0.5) #If you print it, you get 4, So you can use this formula.
def nthrootofm(a,n):
return pow(a,(1/n))
a=81
n=4
q=nthrootofm(a,n)
print(q)
pow () принимает два параметра.