ฉันจะบ้า: ฟังก์ชัน Ruby สำหรับแฟกทอเรียลอยู่ที่ไหน? ไม่ฉันไม่ต้องการการใช้งานบทช่วยสอนฉันแค่ต้องการฟังก์ชันจากไลบรารี มันไม่ได้อยู่ในคณิตศาสตร์!
ฉันเริ่มสงสัยว่ามันเป็นฟังก์ชันไลบรารี่มาตรฐานหรือไม่?
ฉันจะบ้า: ฟังก์ชัน Ruby สำหรับแฟกทอเรียลอยู่ที่ไหน? ไม่ฉันไม่ต้องการการใช้งานบทช่วยสอนฉันแค่ต้องการฟังก์ชันจากไลบรารี มันไม่ได้อยู่ในคณิตศาสตร์!
ฉันเริ่มสงสัยว่ามันเป็นฟังก์ชันไลบรารี่มาตรฐานหรือไม่?
(1..6).inject(:*)
ที่รวบรัดกว่านี้หน่อย
(1..num).inject(:*)
ให้คำตอบที่ถูกต้องสำหรับกรณี 0 และส่งกลับสำหรับพารามิเตอร์เชิงลบ num == 0
(1..(num.zero? ? 1 : num)).inject(:*)
nil
คำตอบ:
ไม่มีฟังก์ชันแฟกทอเรียลในไลบรารีมาตรฐาน
Math.gamma
วิธีการเช่นstackoverflow.com/a/37352690/407213
แบบนี้จะดีกว่า
(1..n).inject(:*) || 1
(1..n).reduce(1, :*)
.
ไม่ได้อยู่ในไลบรารีมาตรฐาน แต่คุณสามารถขยายคลาส Integer ได้
class Integer
def factorial_recursive
self <= 1 ? 1 : self * (self - 1).factorial
end
def factorial_iterative
f = 1; for i in 1..self; f *= i; end; f
end
alias :factorial :factorial_iterative
end
NB Iterative factorial เป็นตัวเลือกที่ดีกว่าสำหรับเหตุผลด้านประสิทธิภาพที่ชัดเจน
เปลนอนอย่างไร้ยางอายจากhttp://rosettacode.org/wiki/Factorial#Rubyรายการโปรดส่วนตัวของฉันคือ
class Integer
def fact
(1..self).reduce(:*) || 1
end
end
>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
การใช้งานนี้เกิดขึ้นได้เร็วที่สุดในบรรดาตัวแปรที่ระบุไว้ใน Rosetta Code
เพิ่ม|| 1
เพื่อจัดการกรณีศูนย์
ขอขอบคุณและขอบคุณMark Thomasนี่คือเวอร์ชันที่มีประสิทธิภาพหรูหราและคลุมเครือเล็กน้อย:
class Integer
def fact
(2..self).reduce(1,:*)
end
end
reduce
(1..self).reduce(1,:*)
(2..self).reduce(1,:*)
ถ้าประสิทธิภาพระดับจุลภาคเป็นของคุณ :)
ในทางคณิตศาสตร์factorial of n
เป็นเพียงgamma function of n+1
(ดู: http://en.wikipedia.org/wiki/Gamma_function )
Ruby Math.gamma()
จึงใช้Math.gamma(n+1)
และส่งกลับเป็นจำนวนเต็มหากต้องการ
คุณยังสามารถใช้Math.gamma
ฟังก์ชันที่เดือดเป็นแฟกทอเรียลสำหรับพารามิเตอร์จำนวนเต็ม
0..22
: MRI Ruby จะทำการค้นหาค่าเหล่านั้นจริง ๆ (ดูstatic const double fact_table[]
ในแหล่งที่มา ) นอกเหนือจากนั้นเป็นค่าประมาณ ตัวอย่างเช่น 23! ต้องการแมนทิสซา 56 บิตซึ่งเป็นไปไม่ได้ที่จะแสดงอย่างแม่นยำโดยใช้ IEEE 754 double ซึ่งมีตั๊กแตนตำข้าว 53 บิต
class Integer
def !
(1..self).inject(:*)
end
end
!3 # => 6
!4 # => 24
class Integer ; def ! ; (1..self).inject(:*) ; end ; end
?
a
เกิดขึ้นInteger
ในกรณี!a
... การทำเช่นนั้นอาจทำให้เกิดข้อผิดพลาดขึ้นซึ่งยากที่จะบอกได้ หากa
เกิดขึ้นเป็นจำนวนมากเช่น357264543
โปรเซสเซอร์กำลังเข้าสู่วงรอบใหญ่และผู้คนอาจสงสัยว่าทำไมโปรแกรมทั้งหมดถึงช้าลงอย่างกะทันหัน
ฉันจะทำ
(1..n).inject(1, :*)
ฉันเพิ่งเขียนของฉันเอง:
def fact(n)
if n<= 1
1
else
n * fact( n - 1 )
end
end
นอกจากนี้คุณสามารถกำหนดแฟกทอเรียลที่ลดลง:
def fall_fact(n,k)
if k <= 0
1
else
n*fall_fact(n - 1, k - 1)
end
end
def factorial(n=0)
(1..n).inject(:*)
end
factorial(3)
factorial(11)
การใช้Math.gamma.floor
เป็นวิธีง่ายๆในการสร้างการประมาณจากนั้นปัดเศษกลับลงมาเป็นผลลัพธ์จำนวนเต็มที่ถูกต้อง ควรใช้กับจำนวนเต็มทั้งหมดรวมการตรวจสอบอินพุตหากจำเป็น
n = 22
สิ้นสุดการให้คำตอบที่แน่นอนและสร้างการประมาณ
ด้วยความเคารพอย่างสูงต่อทุกคนที่เข้าร่วมและสละเวลาเพื่อช่วยเหลือเราฉันต้องการแบ่งปันผลการเปรียบเทียบของโซลูชันที่ระบุไว้ที่นี่ พารามส์:
การทำซ้ำ = 1,000
n = 6
user system total real
Math.gamma(n+1) 0.000383 0.000106 0.000489 ( 0.000487)
(1..n).inject(:*) || 1 0.003986 0.000000 0.003986 ( 0.003987)
(1..n).reduce(1, :*) 0.003926 0.000000 0.003926 ( 0.004023)
1.upto(n) {|x| factorial *= x } 0.003748 0.011734 0.015482 ( 0.022795)
สำหรับ n = 10
user system total real
0.000378 0.000102 0.000480 ( 0.000477)
0.004469 0.000007 0.004476 ( 0.004491)
0.004532 0.000024 0.004556 ( 0.005119)
0.027720 0.011211 0.038931 ( 0.058309)
Math.gamma(n+1)
นั้นเป็นค่าประมาณสำหรับ n> 22 เท่านั้นดังนั้นอาจไม่เหมาะกับทุกกรณีการใช้งาน
เป็นอีกวิธีหนึ่งที่ทำได้แม้ว่าจะไม่จำเป็นจริงๆก็ตาม
class Factorial
attr_reader :num
def initialize(num)
@num = num
end
def find_factorial
(1..num).inject(:*) || 1
end
end
number = Factorial.new(8).find_factorial
puts number
คุณอาจพบว่าคำขอคุณลักษณะ Ruby มีประโยชน์ มันมีขี้ปะติ๋วแพทช์ที่มีการสาธิตสคริปต์ทุบตี ความแตกต่างของความเร็วระหว่างวงรอบไร้เดียงสาและวิธีแก้ปัญหาที่นำเสนอในชุดงานสามารถเท่ากับ 100x (ร้อยเท่า) เขียนด้วยทับทิมแท้ทั้งหมด
นี่คือเวอร์ชันของฉันดูเหมือนจะชัดเจนสำหรับฉันแม้ว่ามันจะไม่สะอาดเท่าก็ตาม
def factorial(num)
step = 0
(num - 1).times do (step += 1 ;num *= step) end
return num
end
นี่คือสายการทดสอบ irb ของฉันที่แสดงแต่ละขั้นตอน
num = 8;step = 0;(num - 1).times do (step += 1 ;num *= step; puts num) end;num
class Integer
def factorial
return self < 0 ? false : self==0 ? 1 : self.downto(1).inject(:*)
#Not sure what other libraries say, but my understanding is that factorial of
#anything less than 0 does not exist.
end
end
และอีกวิธีหนึ่ง (=
def factorial(number)
number = number.to_i
number_range = (number).downto(1).to_a
factorial = number_range.inject(:*)
puts "The factorial of #{number} is #{factorial}"
end
factorial(#number)
อีกหนึ่งวิธีที่ทำได้:
# fact(n) => Computes the Factorial of "n" = n!
def fact(n) (1..n).inject(1) {|r,i| r*i }end
fact(6) => 720
เหตุใดไลบรารีมาตรฐานจึงต้องใช้วิธีแฟกทอเรียลในเมื่อมีตัววนซ้ำในตัวเพื่อจุดประสงค์ที่แน่นอนนี้ เรียกว่าupto
.
ไม่คุณไม่จำเป็นต้องใช้การเรียกซ้ำเหมือนคำตอบอื่น ๆ ที่แสดง
def fact(n)
n == 0 ? 1 : n * fact(n - 1)
end
แต่ตัววนซ้ำในตัวไม่เกินสามารถใช้เพื่อคำนวณแฟกทอเรียลได้:
factorial = 1
1.upto(10) {|x| factorial *= x }
factorial
=> 3628800
6.downto(1).inject(:*)