هل هذا تنفيذ معقول لوظيفة Bézier التربيعية في OCaml؟

StackOverflow https://stackoverflow.com/questions/145056

  •  02-07-2019
  •  | 
  •  

سؤال

صادف أحد الأصدقاء دالة منحنى بيزييه التربيعية في قاعدة التعليمات البرمجية الخاصة به والتي استخدمت مجموعة فئران عملاقة من جدول التبديل لإجراء العمليات الحسابية.لقد تحداني أن أجد تعبيرًا واحدًا قصيرًا يسمح له باستبدال كتلة التعليمات البرمجية الضخمة.

في محاولة لتلبية اثنين من الفضول المختلفة، اعتقدت أنني سأحاول تنفيذ الوظيفة في OCaml.أنا مبرمج OCaml مبتدئ جدًا ولست على دراية أيضًا بالوظيفة وهذا محدد من الصعب الحصول على التنفيذ عبر Google.

تحظى الانتقادات الموجهة إلى أداء/صحة الوظيفة وكذلك تنفيذها بتقدير كبير.

بداية شئ منحنى بيزييه التربيعي:

let rec b2 n =
let p1 = -10. in
let p2 = 10. in
let q = n*.n in
let rec b2i n i hd =
  if i > n then
    List.rev hd
  else
    let t = i /. n in
  b2i n (i+.1.) ((((1.-.t)**2.)*.p1+.(2.*.t*.(1.-.t)*.q)+.(t**2.)*.p2) :: hd)
in b2i n 0. []
;;
let floatprint lst = List.iter (fun f -> Printf.printf "%f; " f) lst ;;
floatprint (b2 8.);;
هل كانت مفيدة؟

المحلول

b2 ليس متكررًا، لذا لا داعي لـ [let rec b2 n =].نظرًا لأن n لا يتغير أبدًا، فلا داعي لاستخدامه كوسيطة لـ b2i، فقط استخدم n من النطاق المرفق.يجب أن تعتمد وظيفتك الداخلية على p0 وp1 وp2، لكنني أراها تعتمد على -10. وn**2 و10.تحتوي الوظيفة أيضًا على شكل خريطة من [ 0.0؛1.0;2.0;...;n.0] إلى القيم النهائية.هل يمكنك كتابتها:

let b i = 
  let t = i /. n in
  let tminus = (1.-.t) in
  (tminus *. tminus *. p0) +. (2. *. t *. tminus *. p1) +. (t *. t * p2)
in
List.map b ([generate list 1.0; 2.0; ... n.0])

دالة لإنشاء القائمة 1.0...n.0 يمكن أن تكون:(للصغيرة ن)

let rec count m n = if m > n then [] else m :: (count (m+.1.) n)

نصائح أخرى

لدي اقتراحان:

يجب عليك الاتصال List.rev بعد b2i يُرجع حتى يتمكن ocaml من استغلال تحسينات التكرار الخلفي الخاصة به.لست متأكدًا من مدى جودة تعامل ocaml مع التنفيذ الحالي، List.rev هو الذيل العودي بالرغم من ذلك.ستلاحظ ذلك في هذا المشنور يتم ذلك على هذا النحو.

يمكنك أيضًا جعل دقة التكرار وسيطة اختيارية مثل ?(epsilon=0.1).

باعتباري مبرمج ocaml، لا أرى خطأً كبيرًا هنا بخلاف ذلك - طالما أن P1 وP2 هما في الواقع ثوابت.قم بتجميعها وانظر ما هو الفرق في التجميع بين نقل List.rev داخل أو خارج العودية الخلفية.

قد يكون هذا picayune، ولكن hd ليس اسمًا جيدًا لمعلمة القائمة. List.hd هي دالة قياسية تقوم بإرجاع العنصر الأول من القائمة.استخدام hd كاسم لقائمة سوف يؤدي إلى الارتباك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top