fraction_approximation.sf 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # License: GPLv3
  4. # Date: 14 July 2017
  5. # https://github.com/trizen
  6. # Simple and efficient algorithm for finding the smallest fraction
  7. # approximation to any given real number, using continued fractions.
  8. func num2cfrac(Block callback, Number n) {
  9. loop {
  10. var m = n.floor.int
  11. callback(m) && return true
  12. n = 1/((n - m) || break)
  13. }
  14. }
  15. func cfrac2num(Array f) {
  16. func (i) {
  17. (i < f.end) ? (f[i] + 1/__FUNC__(i+1)) : f[i]
  18. }(0)
  19. }
  20. func fraction_approximation(Number num) {
  21. num.float!
  22. var rat = 0
  23. var cfrac = []
  24. var str = num.as_dec
  25. num2cfrac({|n|
  26. cfrac.append(n)
  27. rat = cfrac2num(cfrac)
  28. index(rat.as_dec, str) == 0
  29. }, num
  30. )
  31. return rat
  32. }
  33. say fraction_approximation(0.6180339887).as_frac #=> 260497/421493
  34. say fraction_approximation(1.008155930329).as_frac #=> 7293/7234
  35. say fraction_approximation(1.0019891835756).as_frac #=> 524875/523833
  36. say fraction_approximation(529.12424242424).as_frac #=> 174611/330
  37. say fraction_approximation(float(1/6)).as_frac #=> 1/6
  38. say fraction_approximation(float(13/6)).as_frac #=> 13/6
  39. say fraction_approximation(float(6/13)).as_frac #=> 6/13
  40. say fraction_approximation(5.010893246187).as_frac #=> 2300/459
  41. say fraction_approximation(5.054466230936).as_frac #=> 2320/459
  42. say fraction_approximation(5.0108932461873638344226579520697167755991285403).as_frac #=> 2300/459
  43. say fraction_approximation(5.0544662309368191721132897603485838779956427015).as_frac #=> 2320/459