import math
dist = 1
wave = 500e-9
phase = 1
while math.isclose(phase,0) == False:
dist += 1e-9
x = dist % wave
phase = (x % 1) * 2
print(phase)
В Python это код, который я пытаюсь реализовать. Я пытаюсь найти расстояние (начиная с 1 метра при заданной начальной фазе), на котором фаза волны составляет 2pi, и самый простой способ, который я нашел, - это использовать грубую силу в каждом месте; поскольку волна имеет наномасштаб, я считаю, что столкнулся с проблемой преобразования. Любые советы о том, как обойти проблему преобразования?
Я предлагаю последовать предложению AKX и прочитать эту прекрасную страницу документации: docs.python.org/3/tutorial/floatingpoint.html
(x % 1) * 2
никогда не будет 2pi, потому что x % 1
никогда не будет больше 1. Непонятно, что вы пытаетесь сделать или почему вы пытаетесь сделать это таким образом, но похоже, что вы, вероятно, могли бы это сделать. в несколько строк базовой арифметики без перебора.
Где в этом коде вы хотите что-то "сравнить" и в чем проблема?
Также обратите внимание, что math.isclose(x, 0)
совпадает с x == 0
, потому что значение аргумента abs_tol
по умолчанию равно 0.0
(см. документы).
звучит как проблема XY. Можете ли вы подробнее рассказать о проблеме высокого уровня, которую вы пытались решить с помощью грубой силы? Вероятно, есть лучший способ, с математикой.
Вам действительно не нужно «грубо» отвечать, вы можете сделать это с помощью математики. Если вы знаете длину волны (wl
) волны и ее фазу p0
в месте x0
, то фаза 2*pi
в x = x0 + wl * (2*pi - p0) / (2*pi) + n * wl
, где n
— целое неотрицательное число.
@RodrigoRodrigues Я пытаюсь смоделировать эксперимент с двумя щелями, когда фаза света, попадающего в любую щель, различна. мой мыслительный процесс состоит в том, чтобы найти расстояние, на котором фаза световой волны будет равна 2pi для обеих щелей, а затем отодвинуть длину волны от пятна, которое я нахожу, пока два рисунка не перекроются, давая мне самую яркую полосу света.
@PranavHosangadi, где ты нашел это уравнение? я неделю искал такое уравнение
@Bill, когда я настроил abs_tol, я получил тот же результат, и спасибо, я обязательно изучу документы подробнее.
@CameronAustin Я показал причину уравнения в моем ответе ниже. Нигде не нашел, это просто математика.
Вам действительно не нужно «грубо» отвечать, вы можете сделать это с помощью математики.
Рассмотрим простую синусоидальную функцию y = sin(2 pi * (x - x0) / wl + p0)
с начальными условиями p0 = 115
градусов в x0 = 0
и длиной волны wl = 2
from matplotlib import pyplot as plt
import numpy as np
wl = 2
p0 = 115 * np.pi/180
x0 = 0
def func(x):
return np.sin(2 * np.pi * (x - x0) / wl + p0)
x = np.linspace(x0, 10, 10000)
y = func(x)
Фаза меняется на 2*pi
каждый раз, когда мы перемещаем wl
единиц на x
. Чтобы выяснить, насколько мы должны переместиться в x
, чтобы изменить фазу с p0
на 2*pi
, нам нужно решить уравнение:
wl ?
---- = -------------
2*pi (2*pi - p0)
который дает:
? = wl * (2*pi - p0) / (2*pi)
Фаза этой волны 2*pi
впервые в x = x0 + wl * (2pi - p0) / 2pi
. Чтобы получить последующие местоположения, где фаза равна 2*pi
, нам просто нужно перейти вперед на целое число, кратное длине волны. Общая формула будет такой:
xphase_2pi = x0 + wl * (n + (2*pi - p0) / (2*pi))
Реализуя это, мы видим:
Note: I used n = np.arange(0, 5)
to simultaneously calculate 5 points where the phase is 2*pi
xphase_2pi = x0 + wl * (np.arange(0, 5) + (2*np.pi - p0) / (2 * np.pi))
# array([1.36111111, 3.36111111, 5.36111111, 7.36111111, 9.36111111])
yphase_2pi = func(xphase_2pi)
# array([-2.44929360e-16, -4.89858720e-16, -7.34788079e-16, -9.79717439e-16,
-1.22464680e-15])
Как и ожидалось, y
фактически равно нулю, когда фаза синусоиды равна 2*pi
.
Мы также можем построить эти значения, чтобы убедиться:
fig = plt.figure()
plt.plot(x, y)
plt.plot(x0, func(x0), 'ok')
plt.plot(xphase_2pi, yphase_2pi, 'xr')
plt.tight_layout()
plt.grid(True)
График показывает, что все красные символы x
находятся в правильном месте: в нуле, когда волна поднимается.
Если вы настаиваете на том, чтобы сделать это численно, вы можете использовать один из многих удивительных алгоритмов нахождения нуля , с которыми поставляется scipy . Вам действительно не нужно строить свой собственный. Например, вы можете использовать scipy.optimize.fsolve, чтобы решить уравнение, начиная с вашего начального местоположения. Если вы найдете ноль там, где наклон увеличивается, у вас есть ответ! Если вы найдете ноль там, где наклон падает, добавьте к нему wl/2
, и вы получите ответ!
>>> x_zero = scipy.optimize.fsolve(func, x0)
# array([0.36111111])
>>> xphase_2pi = x_zero + np.arange(0, 5) * wl
>>> delta_x = wl / 10000
... slope = (func(x_zero + delta_x) - func(x_zero - delta_x)) / (delta_x * 2)
# array([-3.14159245])
>>> if slope[0] < 0:
... xphase_2pi += wl / 2
Что приводит к тому же xphase_2pi
:
array([1.36111111, 3.36111111, 5.36111111, 7.36111111, 9.36111111])
Если вы все еще хотите построить свой собственный, Метод Ньютона — это классный алгоритм поиска нуля, который вы можете реализовать. Для удобства мы можем определить func_slope
, функцию, которая будет возвращать наклон волны при заданном x
. Наклон рассчитывается как центральная разность по 1/5000
длины волны, как мы делали выше:
def func_slope(func, x):
h = wl / 10000
return (func(x + h) - func(x - h))/ (2 * h)
def newton(func, x0, max_iter=100):
i = 0
x = x0
fx = func(x)
fdx = func_slope(func, x)
while not np.isclose(fx, 0) and i < max_iter:
x = x - fx / fdx
i += 1
fx = func(x)
fdx = func_slope(func, x)
return x, fx, fdx, i
Теперь вы можете вызвать эту функцию:
>>> x_zero, err, slope, iters = newton(func, x0)
# (0.36111111111454486, -1.0787248531787957e-11, -3.1415924468797582, 5)
>>> xphase_2pi = x_zero + np.arange(0, 5) * wl + (slope < 0) * wl / 2
# array([1.36111111, 3.36111111, 5.36111111, 7.36111111, 9.36111111])
Я теряюсь в этом уравнении, которое вы сделали x = x0 + wl * (2pi - p0) / 2pi… y(x) = Asin(x)…..x, что является фазой, или 2pi равно x = ((2pi* x0)/w1) + p0, где я теряюсь, потому что, если бы я продолжал манипулировать этим уравнением, я получил бы x0 = (w1*(x - p0))/2pi или x0 = (w1*(2pi - p0) )/2pi .. это уравнение очень похоже на ваше, но оно достаточно отличается, поэтому я не уверен в ваших шагах. Не могли бы вы подробнее рассказать, как вы это нашли? Спасибо друг
@CameronAustin Общее уравнение волны y = A sin (2 pi / wl * (x - x0) + p0)
для волны, которая, как известно, имеет фазу p0
в x = x0
. Со мной до сих пор? Все, что является аргументом для sin(...)
, является «фазой» волны, поэтому P = 2 pi / wl * (x - x0) + p0
. В x = x0
, P = p0
. Это подтверждает наше граничное условие. Теперь мы знаем, что фаза синусоиды изменяется на 2pi
каждый раз, когда x
изменяется на wl
. И мы знаем, что это началось в p0
. Таким образом, уравнение с неизвестным решает, насколько нам нужно изменить x
, чтобы достичь фазы 2pi
из p0
. Лучше?
о, о, теперь я вижу! спасибо друг, намного лучше.
Вы наверняка сталкиваетесь с неточностью с плавающей запятой. Вы можете просто масштабировать все свои юниты, скажем, на 1e6, а затем снова заняться их масштабированием позже.