Ruby check if even number, float - ruby

I want to check if the number is even!
I tried the following:
a = 4.0
a.is_a? Integer
=> false
a.even?
=> undefined method for Float
So how can i check if the number is even?

If you are unsure if your variable has anything after the decimal and would like to check before converting to integer to check odd/even, you could do something like this:
a = 4.6
b = 4.0
puts a%1==0 && a.to_i.even? #=> false
puts b%1==0 && a.to_i.even? #=> true
Additionally, if you want to create an even? method for the Float class:
class Float
def even?
self%1==0 && self.to_i.even?
end
end
a = 4.6
b = 4.0
a.even? #=> false
b.even? #=> true

Make it an Integer then:
a = 4.0
a.to_i == a && a.to_i.even? #=> true

Just keep in mind how numbers are converted:
(4.0).to_i # same as Integer(4.0)
=> 4
(4.5).to_i
=> 4
(4.9).to_i
=> 4
Using round may be safer:
(4.0).round
=> 4
(4.5).round
=> 5
(4.9).round
=> 5
Then of course you can call even as #Yu Hao wrote:
(4.5).round.even?
=> false
You can also easily observe known floats 'feature':
(4.499999999999999).round.even?
=> true
(4.4999999999999999).round.even?
=> false

Related

How to find a bigger version number?

When compare two version strings, to_f does not work well:
> "1.5.8".to_f > "1.5.7".to_f
=> false
string comparison is better, but not always correct:
> "1.5.8" > "1.5.7"
=> true
> "1.5.8" > "1.5.9"
=> false
> "1.5.8" > "1.5.10" # oops!
=> true
How to compare version strings properly?
An idea: create a Object#compare_by method that behaves like compare (aka the spaceship operator Object#<=>) but takes a custom block:
class Object
def compare_by(other)
yield(self) <=> yield(other)
end
end
>> "1.5.2".compare_by("1.5.7") { |s| s.split(".").map(&:to_i) }
#=> -1
You can also take a more specific approach still based on the compare method:
class String
def compare_by_fields(other, fieldsep = ".")
cmp = proc { |s| s.split(fieldsep).map(&:to_i) }
cmp.call(self) <=> cmp.call(other)
end
end
>> "1.5.8".compare_by_fields("1.5.8")
#=> 0
Personally I'd probably just use the Versionomy gem, no need to reinvent this specific wheel IMHO.
Example:
require 'versionomy'
v1 = Versionomy.parse("1.5.8")
v2 = Versionomy.parse("1.5.10")
v2 > v1
#=> true
First start off by splitting the different parts of the versions:
v1 = "1.5.8"
v2 = "1.5.7"
v1_arr = v1.split(".")
=> ["1", "5", "8"]
v2_arr = v2.split(".")
=> ["1", "5", "7"]
v1_arr.size.times do |index|
if v1_arr[index] != v2_arr[index]
# compare the values at the given index. Don't forget to use to_i!
break
end
end

ruby variable as same object (pointers?)

>> a = 5
=> 5
>> b = a
=> 5
>> b = 4
=> 4
>> a
=> 5
how can I set 'b' to actually be 'a' so that in the example, the variable a will become four as well. thanks.
class Ref
def initialize val
#val = val
end
attr_accessor :val
def to_s
#val.to_s
end
end
a = Ref.new(4)
b = a
puts a #=> 4
puts b #=> 4
a.val = 5
puts a #=> 5
puts b #=> 5
When you do b = a, b points to the same object as a (they have the same object_id).
When you do a = some_other_thing, a will point to another object, while b remains unchanged.
For Fixnum, nil, true and false, you cannot change the value without changing the object_id. However, you can change other objects (strings, arrays, hashes, etc.) without changing object_id, since you don't use the assignment (=).
Example with strings:
a = 'abcd'
b = a
puts a #=> abcd
puts b #=> abcd
a.upcase! # changing a
puts a #=> ABCD
puts b #=> ABCD
a = a.downcase # assigning a
puts a #=> abcd
puts b #=> ABCD
Example with arrays:
a = [1]
b = a
p a #=> [1]
p b #=> [1]
a << 2 # changing a
p a #=> [1, 2]
p b #=> [1, 2]
a += [3] # assigning a
p a #=> [1, 2, 3]
p b #=> [1, 2]
You can't. Variables hold references to values, not references to other variables.
Here's what your example code is doing:
a = 5 # Assign the value 5 to the variable named "a".
b = a # Assign the value in the variable "a" (5) to the variable "b".
b = 4 # Assign the value 4 to the variable named "b".
a # Retrieve the value stored in the variable named "a" (5).
See this article for a more in-depth discussion of the topic: pass by reference or pass by value.
As has been noted the syntax you are using can not be done. Just throwing this out there though you could make a wrapper class it depends what you actually want to do
ruby-1.8.7-p334 :007 > class Wrapper
ruby-1.8.7-p334 :008?> attr_accessor :number
ruby-1.8.7-p334 :009?> def initialize(number)
ruby-1.8.7-p334 :010?> #number = number
ruby-1.8.7-p334 :011?> end
ruby-1.8.7-p334 :012?> end
=> nil
ruby-1.8.7-p334 :013 > a = Wrapper.new(4)
=> #<Wrapper:0x100336db8 #number=4>
ruby-1.8.7-p334 :014 > b = a
=> #<Wrapper:0x100336db8 #number=4>
ruby-1.8.7-p334 :015 > a.number = 6
=> 6
ruby-1.8.7-p334 :016 > a
=> #<Wrapper:0x100336db8 #number=6>
ruby-1.8.7-p334 :017 > b
=> #<Wrapper:0x100336db8 #number=6>
You can use arrays:
a = [5]
b = a
b[0] = 4
puts a[0] #=> 4
This idea is based on this answer.
Just for the sake of reference.
>> a = 5
=> 5
>> a.object_id
=> 11
>> b = a
=> 5
>> b.object_id
=> 11
>> b = 4
=> 4
>> b.object_id
=> 9
>> a.object_id
=> 11
# We did change the Fixnum b Object.
>> Fixnum.superclass
=> Integer
>> Integer.superclass
=> Numeric
>> Numeric.superclass
=> Object
>> Object.superclass
=> BasicObject
>> BasicObject.superclass
=> nil
I hope this gives us all a little better understanding about objects in Ruby.
One option in cases where you feel you would like to have direct pointer operations is to use the replace method of Hashes, Arrays & Strings.
this is useful for when you would like to have a method return a variable that a proc the method sets up will change at a later date, and don't want the annoyance of using a wrapper object.
example:
def hash_that_will_change_later
params = {}
some_resource.on_change do
params.replace {i: 'got changed'}
end
params
end
a = hash_that_will_change_later
=> {}
some_resource.trigger_change!
a
{i: 'got changed'}
It's probably better generally to use explicit object wrappers for such cases, but this pattern is useful for building specs/tests of asynchronous stuff.
I'm no Ruby expert. But for a technically crazy kluge...that would only work if you felt like going through eval every time you worked with a variable:
>> a = 5
=> 5
>> b = :a
=> :a
>> eval "#{b} = 4"
=> 4
>> eval "#{a}"
=> 4
>> eval "#{b}"
=> 4
Note that a direct usage of b will still give you :a and you can't use it in expressions that aren't in eval:
>> b
=> :a
>> b + 1
NoMethodError: undefined method `+' for :a:Symbol
...and there are certainly a ton of caveats. Such as that you'd have to capture the binding and pass it around in more complex scenarios...
'pass parameter by reference' in Ruby?
#Paul.s has an answer for if you can change the point of declaration to be a wrapper object, but if you can only control the point of reference then here's a BasicReference class I tried:
class BasicReference
def initialize(r,b)
#r = r
#b = b
#val = eval "#{#r}", #b
end
def val=(rhs)
#val = eval "#{#r} = #{rhs}", #b
end
def val
#val
end
end
a = 5
puts "Before basic reference"
puts " the value of a is #{a}"
b = BasicReference.new(:a, binding)
b.val = 4
puts "After b.val = 4"
puts " the value of a is #{a}"
puts " the value of b.val is #{b.val}"
This outputs:
Before basic reference
the value of a is 5
After b.val = 4
the value of a is 4
the value of b.val is 4

Is it ok to use `any?` to check if an array is not empty?

Is it bad to check if an array is not empty by using any? method?
a = [1,2,3]
a.any?
=> true
a.clear
a.any?
=> false
Or is it better to use unless a.empty? ?
any? isn't the same as not empty? in some cases.
>> [nil, 1].any?
=> true
>> [nil, nil].any?
=> false
From the documentation:
If the block is not given, Ruby adds
an implicit block of {|obj| obj} (that
is any? will return true if at least
one of the collection members is not
false or nil).
The difference between an array evaluating its values to true or if its empty.
The method empty? comes from the Array class
http://ruby-doc.org/core-2.0.0/Array.html#method-i-empty-3F
It's used to check if the array contains something or not. This includes things that evaluate to false, such as nil and false.
>> a = []
=> []
>> a.empty?
=> true
>> a = [nil, false]
=> [nil, false]
>> a.empty?
=> false
>> a = [nil]
=> [nil]
>> a.empty?
=> false
The method any? comes from the Enumerable module.
http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-any-3F
It's used to evaluate if "any" value in the array evaluates to true.
Similar methods to this are none?, all? and one?, where they all just check to see how many times true could be evaluated. which has nothing to do with the count of values found in a array.
case 1
>> a = []
=> []
>> a.any?
=> false
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> true
case 2
>> a = [nil, true]
=> [nil, true]
>> a.any?
=> true
>> a.one?
=> true
>> a.all?
=> false
>> a.none?
=> false
case 3
>> a = [true, true]
=> [true, true]
>> a.any?
=> true
>> a.one?
=> false
>> a.all?
=> true
>> a.none?
=> false
Avoid any? for large arrays.
any? is O(n)
empty? is O(1)
any? does not check the length but actually scans the whole array for truthy elements.
static VALUE
rb_ary_any_p(VALUE ary)
{
long i, len = RARRAY_LEN(ary);
const VALUE *ptr = RARRAY_CONST_PTR(ary);
if (!len) return Qfalse;
if (!rb_block_given_p()) {
for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue;
}
else {
for (i = 0; i < RARRAY_LEN(ary); ++i) {
if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
}
}
return Qfalse;
}
empty? on the other hand checks the length of the array only.
static VALUE
rb_ary_empty_p(VALUE ary)
{
if (RARRAY_LEN(ary) == 0)
return Qtrue;
return Qfalse;
}
The difference is relevant if you have "sparse" arrays that start with lots of nil values, like for example an array that was just created.
Prefixing the statement with an exclamation mark will let you know whether the array is not empty. So in your case -
a = [1,2,3]
!a.empty?
=> true
I'll suggest using unlessand blank to check is empty or not.
Example :
unless a.blank?
a = "Is not empty"
end
This will know 'a' empty or not.
If 'a' is blank then the below code will not run.
I don't think it's bad to use any? at all. I use it a lot. It's clear and concise.
However if you are concerned about all nil values throwing it off, then you are really asking if the array has size > 0. In that case, this dead simple extension (NOT optimized, monkey-style) would get you close.
Object.class_eval do
def size?
respond_to?(:size) && size > 0
end
end
> "foo".size?
=> true
> "".size?
=> false
> " ".size?
=> true
> [].size?
=> false
> [11,22].size?
=> true
> [nil].size?
=> true
This is fairly descriptive, logically asking "does this object have a size?". And it's concise, and it doesn't require ActiveSupport. And it's easy to build on.
Some extras to think about:
This is not the same as present? from ActiveSupport.
You might want a custom version for String, that ignores whitespace (like present? does).
You might want the name length? for String or other types where it might be more descriptive.
You might want it custom for Integer and other Numeric types, so that a logical zero returns false.

How to convert 1 to "first", 2 to "second", and so on, in Ruby?

Is there a built-in method in Ruby to support this?
if you are in Rails, you can convert 1 to 1st, 2 to 2nd, and so on, using ordinalize.
Example:
1.ordinalize # => "1st"
2.ordinalize # => "2nd"
3.ordinalize # => "3rd"
...
9.ordinalize # => "9th"
...
1000.ordinalize # => "1000th"
And if you want commas in large numbers:
number_with_delimiter(1000, :delimiter => ',') + 1000.ordinal # => "1,000th"
in ruby you do not have this method but you can add your own in Integer class like this.
class Integer
def ordinalize
case self%10
when 1
return "#{self}st"
when 2
return "#{self}nd"
when 3
return "#{self}rd"
else
return "#{self}th"
end
end
end
22.ordinalize #=> "22nd"
How about Linguistics? Its not built in though. If you want built in , you have to set it up using hashes etc..
See here also for examples
I wanted an ordinalize method that has "first, second, third" rather than '1st, 2nd, 3rd' - so here's a little snippet that works up to 10 (and falls back to the Rails ordinalize if it can't find it).
class TextOrdinalize
def initialize(value)
#value = value
end
def text_ordinalize
ordinalize_mapping[#value] || #value.ordinalize
end
private
def ordinalize_mapping
[nil, "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
"eighth", "ninth", "tenth" ]
end
end
Here's how it works:
TextOrdinalize.new(1).text_ordinalize #=> 'first'
TextOrdinalize.new(2).text_ordinalize #=> 'second'
TextOrdinalize.new(0).text_ordinalize #=> '0st'
TextOrdinalize.new(100).text_ordinalize #=> '100th'
if you are not in Rails you could do
def ordinalize(n)
return "#{n}th" if (11..13).include?(n % 100)
case n%10
when 1; "#{n}st"
when 2; "#{n}nd"
when 3; "#{n}rd"
else "#{n}th"
end
end
ordinalize 1
=> "1st"
ordinalize 2
=> "2nd"
ordinalize 11
=> "11th"
Using humanize gem, is probably the easiest way. But, yes, it is not built in, however it has only one dependency, so I think its a pretty good choice..
require 'humanize'
2.humanize => "two"

Is it possible to have class.property = x return something other than x?

Let's say I have a Ruby class:
class MyClass
def self.property
return "someVal"
end
def self.property=(newVal)
# do something to set "property"
success = true
return success # success is a boolean
end
end
If I try and do MyClass.property=x, the return value of the whole statement is always x. It is a convention in a lot of C-based/inspired languages to return a boolean "success" value - is it possible to do this for a setter using the "equals syntax" in Ruby?
Furthermore - if this isn't possible, why not? Is there any conceivable downside to allowing an "equals setter" operation return a value?
One downside is that you would break the chained assignment semantics:
$ irb
irb(main):001:0> x = y = 3
=> 3
irb(main):002:0> p x
3
=> nil
irb(main):003:0> p y
3
=> nil
irb(main):004:0>
Consider:
x = MyClass.property = 3
Then x would take true if this worked as you had expected (right-associativity). That could be a surprise for people using your interface and used to the typical semantics.
You also got me thinking about parallel assignment, eg:
x, y = 1, 2
Apparently the return value from that expression is implementation specific... I guess I won't be chaining parallel assignments :)
Nice question!
Like Martin says, this would break assignment chaining.
The way ruby assignment methods are defined to work expands MyClass.property = 3 to the equivalent of (lambda { |v| MyClass.send('property=', v); v })[3] (not really, but this shows how chaining works). The return value of the assignment is always the value assigned.
If you want to see the result of your MyClass#property= method, then use #send:
irb> o = Object.new
=> #<Object:0x15270>
irb> def o.x=(y)
irb> #x = y+1
irb> puts "y = #{y}, #x = ##x"
irb> true
irb> end
=> nil
irb> def o.x
irb> puts "#x = ##x"
irb> #x
irb> end
=> nil
irb> o.x = 4
y = 4, #x = 5
=> 4
irb> o.x
#x = 5
=> 5
irb> o.send('x=', 3)
y = 3, #x = 4
=> true
However, the ruby way to do this is with exceptions - if something goes wrong during
the assignment, raise an exception. Then all invokers must handle it if something goes
wrong, unlike a return value, which can be easily ignored:
# continued from above...
irb> def o.x=(y)
irb> unless y.respond_to? :> and (y > 0 rescue false)
irb> raise ArgumentError, 'new value must be > 0', caller
irb> end
irb> #x = y + 1
irb> puts "y = #{y}, #x = ##x"
irb> end
=> nil
irb> o.x = 4
y = 4, #x = 5
=> 4
irb> o.x = 0
ArgumentError: new value must be > 0
from (irb):12
from :0
irb> o.x = "3"
ArgumentError: new value must be > 0
from (irb):13
from :0
irb> o.x
#x = 5
=> 5
I'm not a Ruby expert but I'd say no for that case I'm afraid. A property setter is solely there to set the value of a private field, not to have any side effects like returning result codes.
If you want that functionality then forget the setter and write a new method called TrySetProperty or something which tries to set the property and returns a boolean.

Resources