Search code examples
rubyalgorithmnumbersperfect-square

How do I square a number without using multiplication?


Was wondering if there is a way to write a method which squares a number (integer or decimal/float) without using the operational sign (*). For example: square of 2 will be 4, square of 2.5 will be 6.25, and 3.5's will be 12.25.

Here is my approach:

def square(num)
  number = num
  number2 = number
  (1...(number2.floor)).each{ num += number }
  num
end

puts square(2) #=> 4 [Correct]
puts square(16) #=> 256 [Correct]
puts square(2.5) #=> 5.0 [Wrong]
puts square(3.5) #=> 10.5 [Wrong]

The code works for integers, but not with floats/decimals. What am I doing wrong here? Also, if anybody has a fresh approach to this problem then please share. Algorithms are also welcome. Also, considering performance of the method will be a plus.


Solution

  • There are a few tricks you could use, arranged here in order of increasing trickery.

    Logarithms

    Observe that k * k = e^log(k*k) = e^(log(k) + log(k)), and use that rule:

    Math.exp(Math.log(5.2) + Math.log(5.2))
    # => 27.04
    

    No multiplication here!

    Division

    As another commenter suggested, you could take the reciprocal operation, division: k/(1.0/k) == k^2. However, this introduces additional floating-point errors, since k / (1.0 / k) is two floating-point operations, whereas k * k is only one.

    Exponentiation

    Or, since this is Ruby, if you want exactly the same value as the floating-point operation and you don't want to use the multiplication operator, you can use the exponentiation operator: k**2 == k * k.

    Call a web service

    It's not multiplying if you don't do it yourself!

    require 'wolfram'       # https://github.com/cldwalker/wolfram
    query  = 'Square[5.2]'
    result = Wolfram.fetch(query)
    

    Blatant cheating

    Finally, if you're feeling really cheap, you could avoid actually employing the literal "*" operation, and use something equivalent:

    n = ...
    require 'base64'
    n.send (Base64.decode64 'Kg==').to_sym, n    # => n * n