LINUX.ORG.RU

Как избавиться от ошибки (округления?) при вычислении угла (фазы) в numpy.angle?

 , ,


1

3

Имеется массив нулей:

N = 4
h = np.zeros(shape=N)
Как и предполагается, угол элементов в массиве - всегда нули:
np.angle(h)

array([ 0.,  0.,  0.,  0.])
А теперь, берём массив комплексных чисел и умножаем его на ноль, и получаем массив комплексных числе, у которых действительная и мнимая части равны нулю:
noise = np.fft.fft(np.random.normal(size=N))
noise * h
  	
array([ 0.+0.j,  0.-0.j, -0.+0.j, -0.+0.j])
И смотрим его угол:
angle(noise * h)

array([ 0.        , -0.        ,  3.14159265,  3.14159265])
Допустим, -0 еще терпим, но pi на графиках при этом смотрится ужасно - фаза «скачет» от 0 до pi там, где должна строго равняться нулю. Как этого избежать?

P.S. Разумеется, задача не стоит в том, как получить массив «нулей», в реальной задаче h нулевой только в некоторой области, в которой и хочется иметь нулевой угол.

P.P.S. А вот в Matlab такого не наблюдается:

N = 400;
noise = fft(randn(1, N));
h = zeros(1, N);
y = h .* noise;

max(abs(angle(y)))

Matlab постоянно выдаёт строгий ноль.

Перемещено mono из talks

★★★

Последнее исправление: omegatype (всего исправлений: 1)

Понулить элементы массива, модуль которых близок к нулю.

eps = 1e-12
noise[numpy.absolute(noise) < 1e-12] = 0

quoob
()

Тема явно не для Talks.

Deleted
()

То есть питон, умножая число на строгий 0, может получить не ноль? Мощно. А что будет, если умножать не на действительные 0, а на комплексные? То есть вместо h = 0 взять h = 0 + 0*i ?

hotpil ★★★★
()
Ответ на: комментарий от ZERG

Использует как? Можно представить, что он умножает на 0 только модуль, а аргумент оставляет не тронутым. Но это не так, тогда бы не получилось pi в ответе.

hotpil ★★★★
()
Ответ на: комментарий от hotpil

Ноль-то там ноль, только signed https://en.wikipedia.org/wiki/Signed_zero

>>> np.array([1+1j, -1+1j, 1-1j, -1-1j])*0
array([ 0.+0.j, -0.+0.j,  0.+0.j,  0.-0.j])
>>> np.array([1+1j, -1+1j, 1-1j, -1-1j])*0 == 0
array([ True,  True,  True,  True], dtype=bool)

Получившиеся фазы 0 и 180 градусов - очевидно, особенность реализации вычисления фазы в numpy с учётом signed zero; я бы сказал, что определённый смысл в этом есть.

quoob
()
Ответ на: комментарий от hotpil

Вычисления с плавающей точкой вообще противоречат алгебре поля: они [в общем случае] не ассоциативны, не коммутитативны и не дистрибутивны.

На фоне этого разные обозначения нуля, неразличимые обычными операторами сравнения - сущий пустяк.

quoob
()
Ответ на: комментарий от quoob

То есть:

>>> a=-1
>>> print a*0
0
>>> a=-1+1j
>>> print a*0
(-0+0j)

Этот минус ноль появляется только в комплексных числах. Питончег хитер.

hotpil ★★★★
()
Последнее исправление: hotpil (всего исправлений: 2)

Думается, что у нуля угол не определён, отсюда и проблема. Наверное, в твоей библиотеке нет «настоящего» нуля, а есть только численный, который не совсем равен нулю?

den73 ★★★★★
()

Тред не читал. Используй символьные вычисления, например sage.

hlebushek ★★
()

-0.+0.j, -0.+0.j

это уже не ноль, как подметили выше.

аргумент комплексного нуля не определен, отсюда и противоположные результаты. если ты вычисляешь аргумент нуля, ты что-то делаешь не так. попробуй переписать формулы, чтобы избавиться от неопределенностей.

правильный ответ в твоем случае не [0, 0, 0, 0], а [NaN, NaN, NaN, NaN]

MyTrooName ★★★★★
()
Последнее исправление: MyTrooName (всего исправлений: 1)
Ответ на: комментарий от quoob

они [в общем случае] не ассоциативны, не коммутитативны и не дистрибутивны.

Числа IEEE-754 коммутативны, это должно быть экзотика какая-нибудь некоммутативна.

trycatch ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.