Trong toán học, hàm số và các tính chất của hàm số đã được trình bày chặt chẽ, đầy đủ. Do đó bài viết này chỉ đi vào khía cạnh, làm sao để việc hình dung về hàm số được dễ dàng hơn. Từ đó việc áp dụng chúng trong lập trình tính toán sẽ trở nên thuận lợi hơn nhiều. Ta sẽ dùng ngôn ngữ Python để diễn giải về định nghĩa hàm số cũng như cách biểu diễn.
Nhiều người thích thú với mô hình hàm số theo ánh xạ: con bò — xúc xích. Không cần phải suy nghĩ xem con bò có trước hay xúc xích có trước.
Video dưới đây diễn tả một “máy hàm số” hoạt động như thế nào.
Bộ thư viện hỗ trợ Python cần thiết bao gồm:
# Bộ thư viện cần thiết import plotly.graph_objects as go from plotly.subplots import make_subplots import numpy as np
Định nghĩa hàm số
Để hiểu được hàm số là gì, hãy xét hai dãy số \(x\) và \(y\) dưới đây
x = np.array([0,1,2,3,4,5]) # giay y = np.array([0,1.5,3.6,9.3,16.3,23.5]) # met print('x =',x) print('y =',y)
Kết quả xuất ra màn hình:
x = [0 1 2 3 4 5] y = [ 0. 1.5 3.6 9.3 16.3 23.5]
Chúng có số lượng phần tử như nhau. Phần tử đầu tiên của \(y\) tương ứng với phần tử đầu tiên của \(x\), phần tử thứ \(i\) của \(y\) tương ứng với phần tử thứ \(i\) của \(x\). Dãy \(x\) ta gọi là biến số, còn dãy \(y\) ta gọi là đối số. Hai dãy này kẹp vào nhau, cứ mỗi \(x\) tồn tại đều được đáp trả với mỗi \(y\) tương ứng như vậy, ta gọi là hàm số, kí hiệu \(y(x)\).
Đồ thị của hàm số \(y(x)\) là tập hợp các điểm có tọa độ \((x_i,y_i)\) trên hệ trục tọa độ. Với hệ trục tọa độ Decasters, đồ thị của hàm số trên biểu diễn thành bộ các điểm như hình dưới.
fig = go.Figure() fig.add_trace(go.Scatter(x=x,y=y,mode='markers',name='y(x)', marker=dict(color='red',line_width=0,line_color='red'))) fig.update_layout(title='Đồ thị hàm số y(x)', xaxis_title='x [m]', yaxis_title='y [m]')
Nhiều khi ta nối các điểm lại với nhau bằng đoạn thẳng:
fig = go.Figure() fig.add_trace(go.Scatter(x=x,y=y,mode='lines+markers',name='y(x)', marker=dict(color='red',line_width=0,line_color='red'), line=dict(color='blue',width=1.5))) fig.update_layout(title='Đồ thị hàm số y(x)', xaxis_title='x [m]', yaxis_title='y [m]')
Hàm số giải tích
Trong toán học, hàm số giải tích có định nghĩa chặt chẽ hơn. Trong bài viết này ta chỉ để ý đến một tính chất quan trọng của hàm giải tích: giữa hai điểm \((x_i,y_i)\) và \((x_j,y_j)\) luôn tồn tại (hay tìm thấy) một điểm \((x_k,y_k)\) chen giữa.
Nói cách khác, hàm giải tích có vô số phần tử. Khi “phóng đại” một góc nhỏ trên đồ thị của một hàm giải tích, đồ thị không bị giãn ra thành các điểm rời rạc xa nhau mà luôn luôn có các điểm trung gian lấp đầy.
Vì vậy, ta không thể diễn tả một hàm giải thích dưới dạng bảng, dạng hai dãy số rời rạc, mà thông qua biểu thức đại số.
Ví dụ xét hàm số giải tích \(y=x^2+x+1\). Hàm này có thể định nghĩa bằng ngôn ngữ Python như sau:
def parabol_1(x): return x**2+x+1
Định nghĩa này cho phép ta diễn giải hàm số dưới dạng hai dãy số. Biến số \(x\) được gán cụ thể, ví dụ từ -3 đến 3 với 100 điểm cách đều nhau, được tạo ra bởi lệnh:
x = np.linspace(-3,3,100) display(x)
Kết quả xuất hiện trên màn hình:
array([-3. , -2.93939394, -2.87878788, -2.81818182, -2.75757576, -2.6969697 , -2.63636364, -2.57575758, -2.51515152, -2.45454545, -2.39393939, -2.33333333, -2.27272727, -2.21212121, -2.15151515, -2.09090909, -2.03030303, -1.96969697, -1.90909091, -1.84848485, -1.78787879, -1.72727273, -1.66666667, -1.60606061, -1.54545455, -1.48484848, -1.42424242, -1.36363636, -1.3030303 , -1.24242424, -1.18181818, -1.12121212, -1.06060606, -1. , -0.93939394, -0.87878788, -0.81818182, -0.75757576, -0.6969697 , -0.63636364, -0.57575758, -0.51515152, -0.45454545, -0.39393939, -0.33333333, -0.27272727, -0.21212121, -0.15151515, -0.09090909, -0.03030303, 0.03030303, 0.09090909, 0.15151515, 0.21212121, 0.27272727, 0.33333333, 0.39393939, 0.45454545, 0.51515152, 0.57575758, 0.63636364, 0.6969697 , 0.75757576, 0.81818182, 0.87878788, 0.93939394, 1. , 1.06060606, 1.12121212, 1.18181818, 1.24242424, 1.3030303 , 1.36363636, 1.42424242, 1.48484848, 1.54545455, 1.60606061, 1.66666667, 1.72727273, 1.78787879, 1.84848485, 1.90909091, 1.96969697, 2.03030303, 2.09090909, 2.15151515, 2.21212121, 2.27272727, 2.33333333, 2.39393939, 2.45454545, 2.51515152, 2.57575758, 2.63636364, 2.6969697 , 2.75757576, 2.81818182, 2.87878788, 2.93939394, 3. ])
Từ đây đối số \(y\) sẽ có đúng 100 phần tử miêu tả qua biểu thức \(y=x^2+x+1\):
y = parabol_1(x) display(y)
array([ 7. , 6.70064279, 6.40863177, 6.12396694, 5.8466483 , 5.57667585, 5.31404959, 5.05876951, 4.81083563, 4.57024793, 4.33700643, 4.11111111, 3.89256198, 3.68135904, 3.4775023 , 3.28099174, 3.09182736, 2.91000918, 2.73553719, 2.56841139, 2.40863177, 2.25619835, 2.11111111, 1.97337006, 1.84297521, 1.71992654, 1.60422406, 1.49586777, 1.39485767, 1.30119376, 1.21487603, 1.1359045 , 1.06427916, 1. , 0.94306703, 0.89348026, 0.85123967, 0.81634527, 0.78879706, 0.76859504, 0.75573921, 0.75022957, 0.75206612, 0.76124885, 0.77777778, 0.80165289, 0.8328742 , 0.87144169, 0.91735537, 0.97061524, 1.0312213 , 1.09917355, 1.17447199, 1.25711662, 1.34710744, 1.44444444, 1.54912764, 1.66115702, 1.7805326 , 1.90725436, 2.04132231, 2.18273646, 2.33149679, 2.48760331, 2.65105601, 2.82185491, 3. , 3.18549128, 3.37832874, 3.5785124 , 3.78604224, 4.00091827, 4.2231405 , 4.45270891, 4.68962351, 4.9338843 , 5.18549128, 5.44444444, 5.7107438 , 5.98438935, 6.26538108, 6.55371901, 6.84940312, 7.15243343, 7.46280992, 7.7805326 , 8.10560147, 8.43801653, 8.77777778, 9.12488522, 9.47933884, 9.84113866, 10.21028466, 10.58677686, 10.97061524, 11.36179982, 11.76033058, 12.16620753, 12.57943067, 13. ])
Đồ thị hàm số với 100 điểm \((x_i,y_i)\) này đủ dày, khiến ta cảm tưởng về một đường cong mịn của một hàm số giải tích:
fig = go.Figure() fig.add_trace(go.Scatter(x=x,y=y,mode='lines+markers',name='y(x)', marker=dict(color='red',line_width=0,line_color='red'), line=dict(color='blue',width=1.5))) fig.update_layout(title='Đồ thị hàm số y(x)', xaxis_title='x [m]', yaxis_title='y [m]')
Hàm số cho dưới dạng tham số
Xét một chuyển động đều trên quỹ đạo tròn bán kính \(r=3\), tốc độ góc \(\omega=1\,\mathrm{rad/s}\). Hoành độ và tung độ thay đổi theo thời gian với quy luật:
$$x=3\cos(\omega t),\\
y=3\sin(\omega t).$$
r = 3 omega = 1 t = np.linspace(0,7,100) x = r*np.cos(omega*t) y = r*np.sin(omega*t)
Những quy luật biến đổi của toạ độ theo thời gian này chúng ta gọi là phương trình chuyển động. Bản thân chúng là các hàm số của toạ độ theo thời gian: \(x(t)\) và \(y(t)\). Đồ thị hàm số \(x(t)\) và \(y(t)\) được gọi là đồ thị của phương trình chuyển động. Trên python có thể vẽ qua lệnh:
fig = make_subplots(subplot_titles=("Hàm số x(t)", "Hàm số y(t)"),rows=2,cols=1) fig.add_trace(go.Scatter(x=t,y=x,mode='lines+markers',name='x(t)'),row=1,col=1) fig.add_trace(go.Scatter(x=t,y=y,mode='lines+markers',name='y(t)'),row=2,col=1) fig.update_xaxes(title_text='t [s]',row=1,col=1) fig.update_yaxes(title_text='x [m]',row=1,col=1) fig.update_xaxes(title_text='t [m]',row=2,col=1) fig.update_yaxes(title_text='y [m]',row=2,col=1)
Thời gian trôi đi, cứ mỗi thời điểm \(t_i\) sẽ tương ứng với một vị trí \((x_i,y_i)\). Kết quả là, cứ mỗi hoành độ \(x_i\) cũng sẽ tương ứng với một tung độ \(y_i\). Nói cách khác, hai dãy giá trị \(x\) và \(y\) cũng có thể kẹp thành một hàm số với biểu diễn kí hiệu \(y(x)\). Trong vật lý, hàm \(y(x)\) gọi là phương trình quỹ đạo, còn đồ thị của nó thể hiện hình dáng của quỹ đạo.
fig = go.Figure() fig.add_trace(go.Scatter(x=x,y=y,mode='lines+markers',name='y(x)', marker=dict(color='red',line_width=0,line_color='red'), line=dict(color='green',width=1.5))) fig.update_layout(title='Đồ thị hàm số y(x)', xaxis_title='x [m]', yaxis_title='y [m]') fig.update_xaxes( range=[-4,4], constrain="domain", ) fig.update_yaxes( scaleanchor = "x", scaleratio = 1, )
Phương trình quỹ đạo trên có dạng đường tròn.
Hàm số ngược
Xét hàm số \(y(x)=x^2\) với tập xác định từ 0 đến 1.5 được định nghĩa bằng Python như sau:
x = np.linspace(0,1.5,20) y = x**2
Ta đặt câu hỏi: Vậy nếu cho trước giá trị \(y\), thì với giá trị nào của \(x\) bình phương lên sẽ cho ra giá trị \(y\) đó? Trong toán học chúng ta định nghĩa rằng, giá trị \(x\) nào khi bình phương lên mà cho ra giá trị \(y\) thì ta gọi \(x\) là “gốc rễ” – hay “cội nguồn” – của \(y\):
$$x=\sqrt{y}$$
Gọi theo Hán – Việt là “căn”. Hàm số \(x=\sqrt{y}\) gọi là hàm số ngược của \(y=x^2\). Chỉ cần đổi hai trục, trục \(y\) thành trục \(x\) và trục \(x\) thành trục \(y\) là ta có được đồ thị hàm số ngược.
fig = go.Figure() fig.add_trace(go.Scatter(x=x,y=y,mode='lines+markers',name='$y(x)=x^2$', marker=dict(color='blue',line_width=0,line_color='blue'), line=dict(color='blue',width=1.5))) fig.update_layout(title='Đồ thị hàm số y(x)', xaxis_title='x [m]', yaxis_title='y [m]') fig.add_trace(go.Scatter(x=y,y=x,mode='lines+markers',name='$x(y)=\sqrt{y}$', marker=dict(color='green',line_width=0,line_color='green'), line=dict(color='green',width=1.5))) fig.update_layout(title='Đồ thị hàm số ngược', xaxis_title='x [m]', yaxis_title='y [m]') fig.update_xaxes( range=[-1,3], constrain="domain", ) fig.update_yaxes( scaleanchor = "x", scaleratio = 1, )
Kết luận
Hàm số hiểu theo ngôn ngữ ánh xạ song ánh như diễn tả trong bài viết này thuận tiện cho việc tính toán và triển khai vẽ đồ thị. Ta có thể dựng đồ thị cho đường cong của hàm đa trị (một giá trị \(x\) tương ứng nhiều giá trị \(y\)) không hề khó khăn.
Tác giả: Trần Hải Cát