# Logical Operations on Strings

**URL:** <https://rubytalk.org/t/logical-operations-on-strings/44079>\
**Category:** ruby-talk\
**Created:** [28 January 2008 08:20 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079 "2008-01-28T08:20:24Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Michael\_W\_Ryder1](https://avatars.discourse-cdn.com/v4/letter/m/8e7dd6/32.png) [@Michael\_W\_Ryder1](https://rubytalk.org/u/Michael_W_Ryder1)\
**Post date:** [28 January 2008 08:20 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079/1 "2008-01-28T08:20:24Z")

</div>

Is there a bitwise and for strings that I am missing? I tried the documentation and Google with no luck. I coded a simple method to handle this, it obviously needs more error checking, but don't want to reinvent the wheel if not necessary.

def AND(s, m)  
&nbsp;&nbsp;&nbsp;t = s.dup  
&nbsp;&nbsp;&nbsp;for i in 0...(s.size \<= m.size ? s.size : m.size)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[i] = (s[i] & m[i]).chr  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;return t  
end

On a related note, is there any way to create a string from a hex number other than separating each two digits and using .chr to convert them to a number and adding them to the string? If I have a string such as 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by 5 str1 \<\< 0xFF.chr which seems to be unnecessarily clumsy.

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [28 January 2008 10:09 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079/2 "2008-01-28T10:09:14Z")

</div>

> Is there a bitwise and for strings that I am missing? I tried the  
> documentation and Google with no luck. I coded a simple method to  
> handle this, it obviously needs more error checking, but don't want to  
> reinvent the wheel if not necessary.
> 
> def AND(s, m)  
> &nbsp;&nbsp;&nbsp;t = s.dup  
> &nbsp;&nbsp;&nbsp;for i in 0...(s.size \<= m.size ? s.size : m.size)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[i] = (s[i] & m[i]).chr  
> &nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;return t  
> end

I believe this implementation is flawed because it returns a string  
that is too long if self.size \> m.size.

This is what I'd probably do

class String  
&nbsp;&nbsp;def &(s)  
&nbsp;&nbsp;&nbsp;&nbsp;t = ""  
&nbsp;&nbsp;&nbsp;&nbsp;[size, s.size].min.times do |i|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t \<\< (self[i] & s[i])  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;t  
&nbsp;&nbsp;end

&nbsp;&nbsp;def |(s)  
&nbsp;&nbsp;&nbsp;&nbsp;t = ""  
&nbsp;&nbsp;&nbsp;&nbsp;[size, s.size].max.times do |i|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t \<\< ((self[i] || 0) | (s[i] || 0))  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;t  
&nbsp;&nbsp;end  
end

Now you can do

irb(main):020:0\> 0.chr | "a"  
=\> "a"  
irb(main):021:0\> 0.chr | "abc"  
=\> "abc"  
irb(main):022:0\> 0.chr & "abc"  
=\> "\000"  
irb(main):023:0\> a="s"  
=\> "s"  
irb(main):024:0\> a|="123"  
=\> "s23"  
irb(main):025:0\> a&="\012"  
=\> "\002"

> On a related note, is there any way to create a string from a hex number  
> other than separating each two digits and using .chr to convert them to  
> a number and adding them to the string? If I have a string such as  
> 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by  
> 5 str1 \<\< 0xFF.chr which seems to be unnecessarily clumsy.

I am not sure which direction you mean (there is no such thing as a  
"hex number" in Ruby, a number is a number, hex is just one  
representation - internally they are most likely stored binary). Does  
this help?

irb(main):001:0\> 123.to\_s 16  
=\> "7b"  
irb(main):002:0\> "%04x" % 123  
=\> "007b"  
irb(main):003:0\> "7b".to\_i 16  
=\> 123

Kind regards

robert

> **···**
>
> 2008/1/28, Michael W. Ryder \<\_mwryder@worldnet.att.net\>:
> 
> --  
> use.inject do |as, often| as.you\_can - without end

---

<div class="post-metadata">

**Author:** ![Michael\_W\_Ryder1](https://avatars.discourse-cdn.com/v4/letter/m/8e7dd6/32.png) [@Michael\_W\_Ryder1](https://rubytalk.org/u/Michael_W_Ryder1)\
**Post date:** [28 January 2008 20:04 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079/3 "2008-01-28T20:04:56Z")

</div>

Robert Klemme wrote:

> > Is there a bitwise and for strings that I am missing? I tried the  
> > documentation and Google with no luck. I coded a simple method to  
> > handle this, it obviously needs more error checking, but don't want to  
> > reinvent the wheel if not necessary.
> > 
> > def AND(s, m)  
> > &nbsp;&nbsp;&nbsp;t = s.dup  
> > &nbsp;&nbsp;&nbsp;for i in 0...(s.size \<= m.size ? s.size : m.size)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t[i] = (s[i] & m[i]).chr  
> > &nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;return t  
> > end
> 
> I believe this implementation is flawed because it returns a string  
> that is too long if self.size \> m.size.

Actually I designed it that way so that I could change only part of the original string without having to create a mask of 0xFF for the remaining characters. Your implementations look a little cleaner than my first try and I will probably use them in the finished version. I still wonder why these weren't implemented in Ruby as I have been using them for over 25 years in other languages.

> This is what I'd probably do
> 
> class String  
> &nbsp;&nbsp;def &(s)  
> &nbsp;&nbsp;&nbsp;&nbsp;t = ""  
> &nbsp;&nbsp;&nbsp;&nbsp;[size, s.size].min.times do |i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t \<\< (self[i] & s[i])  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;t  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def |(s)  
> &nbsp;&nbsp;&nbsp;&nbsp;t = ""  
> &nbsp;&nbsp;&nbsp;&nbsp;[size, s.size].max.times do |i|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t \<\< ((self[i] || 0) | (s[i] || 0))  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;t  
> &nbsp;&nbsp;end  
> end
> 
> Now you can do
> 
> irb(main):020:0\> 0.chr | "a"  
> =\> "a"  
> irb(main):021:0\> 0.chr | "abc"  
> =\> "abc"  
> irb(main):022:0\> 0.chr & "abc"  
> =\> "\000"  
> irb(main):023:0\> a="s"  
> =\> "s"  
> irb(main):024:0\> a|="123"  
> =\> "s23"  
> irb(main):025:0\> a&="\012"  
> =\> "\002"
> 
> > On a related note, is there any way to create a string from a hex number  
> > other than separating each two digits and using .chr to convert them to  
> > a number and adding them to the string? If I have a string such as  
> > 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by  
> > 5 str1 \<\< 0xFF.chr which seems to be unnecessarily clumsy.
> 
> I am not sure which direction you mean (there is no such thing as a  
> "hex number" in Ruby, a number is a number, hex is just one  
> representation - internally they are most likely stored binary). Does  
> this help?

The reason I asked is that sometimes it is easier for me to think in hex when creating masks for logical operations. Plus, I learned the PCL codes for printing using hex and it is easier for me to use them that way. In Business Basic to enter a group of hex characters into a string I just use A$=$1B2C062C$ to create a 4 character string. No need to enter each character individually.

> **···**
>
> > 2008/1/28, Michael W. Ryder \<\_mwryder@worldnet.att.net\>:
> 
> > irb(main):001:0\> 123.to\_s 16  
> > =\> "7b"  
> > irb(main):002:0\> "%04x" % 123  
> > =\> "007b"  
> > irb(main):003:0\> "7b".to\_i 16  
> > =\> 123
> > 
> > Kind regards
> > 
> > robert

---

<div class="post-metadata">

**Author:** ![Adam\_Shelly](https://avatars.discourse-cdn.com/v4/letter/a/e19b73/32.png) [@Adam\_Shelly](https://rubytalk.org/u/Adam_Shelly)\
**Post date:** [28 January 2008 20:37 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079/4 "2008-01-28T20:37:54Z")

</div>

Are you looking for something like this?

irb(main):010:0\> ["414243"].pack('H\*')  
=\> "ABC"  
irb(main):011:0\> ["7FFFFFFFFFFF"].pack('H\*')  
=\> "\177\377\377\377\377\377"  
irb(main):012:0\> A=['1B2C062C'].pack('H\*')  
=\> "\e,\006,"

-Adam

> **···**
>
> On 1/28/08, Michael W. Ryder \<\_mwryder@worldnet.att.net\> wrote:
> 
> > Robert Klemme wrote:  
> > \> 2008/1/28, Michael W. Ryder \<\_mwryder@worldnet.att.net\>:  
> > \>\> On a related note, is there any way to create a string from a hex number  
> > \>\> other than separating each two digits and using .chr to convert them to  
> > \>\> a number and adding them to the string? If I have a string such as  
> > \>\> 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by  
> > \>\> 5 str1 \<\< 0xFF.chr which seems to be unnecessarily clumsy.  
> > \>  
> > The reason I asked is that sometimes it is easier for me to think in hex  
> > when creating masks for logical operations. Plus, I learned the PCL  
> > codes for printing using hex and it is easier for me to use them that  
> > way. In Business Basic to enter a group of hex characters into a string  
> > I just use A$=$1B2C062C$ to create a 4 character string. No need to  
> > enter each character individually.

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [29 January 2008 08:36 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079/5 "2008-01-29T08:36:59Z")

</div>

> Robert Klemme wrote:  
> \> I believe this implementation is flawed because it returns a string  
> \> that is too long if self.size \> m.size.
> 
> Actually I designed it that way so that I could change only part of the  
> original string without having to create a mask of 0xFF for the  
> remaining characters.

Ah, ok, then this was on purpose. Personally I'd consider an element  
that is not there as 0x00 for OR and AND - that's why I did it this  
way.

> Your implementations look a little cleaner than  
> my first try and I will probably use them in the finished version. I  
> still wonder why these weren't implemented in Ruby as I have been using  
> them for over 25 years in other languages.

Since Ruby is so flexible chances are that you will find an equally  
easy (or easier) way. 🙂

> The reason I asked is that sometimes it is easier for me to think in hex  
> when creating masks for logical operations. Plus, I learned the PCL  
> codes for printing using hex and it is easier for me to use them that  
> way. In Business Basic to enter a group of hex characters into a string  
> I just use A$=$1B2C062C$ to create a 4 character string. No need to  
> enter each character individually.

Then #pack and #unpack are your friends (see Adam's reply). You could  
easily put that in a method if you want a more concise representation,  
e.g.

def h(s)  
&nbsp;&nbsp;[s.to\_str].pack 'H\*'  
end

irb(main):005:0\> h '212223'  
=\> "!\"#"  
irb(main):006:0\> h '414243'  
=\> "ABC"  
irb(main):010:0\> h %Q{414243}  
=\> "ABC"  
irb(main):011:0\> h %q{414243}  
=\> "ABC"

Note also, that you can use hex constants in Ruby:

irb(main):001:0\> 0x7b  
=\> 123

but it seems you are more after construction of strings.

Kind regards

robert

> **···**
>
> 2008/1/28, Michael W. Ryder \<\_mwryder@worldnet.att.net\>:
> 
> --  
> use.inject do |as, often| as.you\_can - without end

---

<div class="post-metadata">

**Author:** ![Michael\_W\_Ryder1](https://avatars.discourse-cdn.com/v4/letter/m/8e7dd6/32.png) [@Michael\_W\_Ryder1](https://rubytalk.org/u/Michael_W_Ryder1)\
**Post date:** [28 January 2008 23:04 UTC](https://rubytalk.org/t/logical-operations-on-strings/44079/6 "2008-01-28T23:04:59Z")

</div>

Adam Shelly wrote:

> **···**
>
> > On 1/28/08, Michael W. Ryder \<\_mwryder@worldnet.att.net\> wrote:
> > 
> > > Robert Klemme wrote:
> > > 
> > > > 2008/1/28, Michael W. Ryder \<\_mwryder@worldnet.att.net\>:
> > > > 
> > > > > On a related note, is there any way to create a string from a hex number  
> > > > > other than separating each two digits and using .chr to convert them to  
> > > > > a number and adding them to the string? If I have a string such as  
> > > > > 0x7FFFFFFFFFFF I have to use something like str1 = 0x7F.chr followed by  
> > > > > 5 str1 \<\< 0xFF.chr which seems to be unnecessarily clumsy.
> > > 
> > > The reason I asked is that sometimes it is easier for me to think in hex  
> > > when creating masks for logical operations. Plus, I learned the PCL  
> > > codes for printing using hex and it is easier for me to use them that  
> > > way. In Business Basic to enter a group of hex characters into a string  
> > > I just use A$=$1B2C062C$ to create a 4 character string. No need to  
> > > enter each character individually.
> > 
> > Are you looking for something like this?
> > 
> > irb(main):010:0\> ["414243"].pack('H\*')  
> > =\> "ABC"  
> > irb(main):011:0\> ["7FFFFFFFFFFF"].pack('H\*')  
> > =\> "\177\377\377\377\377\377"  
> > irb(main):012:0\> A=['1B2C062C'].pack('H\*')  
> > =\> "\e,\006,"
> > 
> > -Adam
> 
> That is much better, I will have to read up on pack and template strings now but at least I have a starting point. It's not as concise as what I am used to but it is usable. Thank you for pointing this out.
