Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions spec/std/float_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,26 @@ describe "Float" do
it { -1.4.divmod(-0.3)[1].should be_close(-0.2, 0.00001) }
end

describe "floor division //" do
it "preserves type of lhs" do
(7.0 // 2).should be_a(Float64)
(7.0 // 2i32).should be_a(Float64)
(7.0 // 2.0).should be_a(Float64)
(7.0_f32 // 2.0_f64).should be_a(Float32)
(7.0_f32 // 2.0_f32).should be_a(Float32)
end

it "applies floor" do
(7.0 // 2.0).should eq(3.0)
(-7.0 // 2.0).should eq(-4.0)

(6.0 // 2.0).should eq(3.0)
(-6.0 // 2.0).should eq(-3.0)

(30.3 // 3.9).should eq(7.0)
end
end

describe "to_s" do
it "does to_s for f64" do
12.34.to_s.should eq("12.34")
Expand Down
36 changes: 36 additions & 0 deletions spec/std/int_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,28 @@ describe "Int" do
(-6 / -2).should eq(3)
end

describe "floor division //" do
it "preserves type of lhs" do
{% for type in [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64] %}
({{type}}.new(7) // 2).should be_a({{type}})
({{type}}.new(7) // 2.0).should be_a({{type}})
({{type}}.new(7) // 2.0_f32).should be_a({{type}})
{% end %}
end

it "divides negative numbers" do
(7 // 2).should eq(3)
(-7 // 2).should eq(-4)
(7 // -2).should eq(-4)
(-7 // -2).should eq(3)

(6 // 2).should eq(3)
(-6 // 2).should eq(-3)
(6 // -2).should eq(-3)
(-6 // -2).should eq(3)
end
end

it "tdivs" do
5.tdiv(3).should eq(1)
-5.tdiv(3).should eq(-1)
Expand All @@ -383,6 +405,11 @@ describe "Int" do
(4 / 2).should eq(2)
end

it "raises when divides by zero" do
expect_raises(DivisionByZeroError) { 1 // 0 }
(4 // 2).should eq(2)
end

it "raises when divides Int::MIN by -1" do
expect_raises(ArgumentError) { Int8::MIN / -1 }
expect_raises(ArgumentError) { Int16::MIN / -1 }
Expand All @@ -392,6 +419,15 @@ describe "Int" do
(UInt8::MIN / -1).should eq(0)
end

it "raises when divides Int::MIN by -1" do
expect_raises(ArgumentError) { Int8::MIN // -1 }
expect_raises(ArgumentError) { Int16::MIN // -1 }
expect_raises(ArgumentError) { Int32::MIN // -1 }
expect_raises(ArgumentError) { Int64::MIN // -1 }

(UInt8::MIN // -1).should eq(0)
end

it "raises when mods by zero" do
expect_raises(DivisionByZeroError) { 1 % 0 }
(4 % 2).should eq(0)
Expand Down
4 changes: 4 additions & 0 deletions src/float.cr
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ struct Float
self.class.zero - self
end

def //(other)
(self / other).floor
end

def %(other)
modulo(other)
end
Expand Down
14 changes: 13 additions & 1 deletion src/int.cr
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ struct Int
# Raises if *other* is zero, or if *other* is -1 and
# `self` is signed and is the minimum value for that
# integer type.
def /(other : Int)
def //(other : Int)
check_div_argument other

div = unsafe_div other
Expand All @@ -107,6 +107,18 @@ struct Int
div
end

# Divides `self` by *other* as floating point numbers and
# applies the floor function to that result.
#
# The result will be of the same type as `self`.
def //(other : Float)
self.class.new(to_f // other)
end

def /(other : Int)
self // other
end

# Divides `self` by *other* using truncated division.
#
# In truncated division, given two integers x and y:
Expand Down