From 7eedaf0fa2e06558ca27f7ad1badfa9cd8f5f858 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Fri, 28 Sep 2018 18:35:52 -0300 Subject: [PATCH 1/2] Add floor divisions operator --- spec/std/float_spec.cr | 18 ++++++++++++++++++ spec/std/int_spec.cr | 36 ++++++++++++++++++++++++++++++++++++ src/float.cr | 4 ++++ src/int.cr | 14 +++++++++++++- 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/spec/std/float_spec.cr b/spec/std/float_spec.cr index fcfd16bf6ad4..e0436f1e0a49 100644 --- a/spec/std/float_spec.cr +++ b/spec/std/float_spec.cr @@ -120,6 +120,24 @@ 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) + (-7.0 // 2.0).should eq(-4) + + (6.0 // 2.0).should eq(3) + (-6.0 // 2.0).should eq(-3) + end + end + describe "to_s" do it "does to_s for f64" do 12.34.to_s.should eq("12.34") diff --git a/spec/std/int_spec.cr b/spec/std/int_spec.cr index 1137c9e7d284..f96fe6aed3de 100644 --- a/spec/std/int_spec.cr +++ b/spec/std/int_spec.cr @@ -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) @@ -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 } @@ -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) diff --git a/src/float.cr b/src/float.cr index 1544d4876106..fed35eb35987 100644 --- a/src/float.cr +++ b/src/float.cr @@ -41,6 +41,10 @@ struct Float self.class.zero - self end + def //(other) + (self / other).floor + end + def %(other) modulo(other) end diff --git a/src/int.cr b/src/int.cr index b9433908bc42..297c97ffccc4 100644 --- a/src/int.cr +++ b/src/int.cr @@ -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 @@ -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: From f6445705d9f027978d9325c0bfd8f625b679b23a Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" Date: Thu, 11 Oct 2018 16:22:07 -0300 Subject: [PATCH 2/2] fixup! Add floor divisions operator --- spec/std/float_spec.cr | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/std/float_spec.cr b/spec/std/float_spec.cr index e0436f1e0a49..a3f4609e0aa5 100644 --- a/spec/std/float_spec.cr +++ b/spec/std/float_spec.cr @@ -130,11 +130,13 @@ describe "Float" do end it "applies floor" do - (7.0 // 2.0).should eq(3) - (-7.0 // 2.0).should eq(-4) + (7.0 // 2.0).should eq(3.0) + (-7.0 // 2.0).should eq(-4.0) - (6.0 // 2.0).should eq(3) - (-6.0 // 2.0).should eq(-3) + (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