On Aug 31, 2015, at 10:05 AM, Mike - st257 <silvertip257 at gmail.com> wrote:> > On Mon, Aug 31, 2015 at 11:15 AM, Warren Young <wyml at etr-usa.com> wrote: > >> ibase=A and obase=A > > Not sure how this helps me with my most recent example of bin_to_hex where > the ibase within the define clause wasn't honored.That?s because your bin_to_hex function is erroneously assuming that its input is just a string of digits that has no base interpretation, so that it can set ibase *after* bc has already seen the value, and that this will change the meaning of the prior input. That?s just plain wrong: the prior input has already been interpreted. You can?t wind back the clock like that. That sort of thinking only works in a string-based language like shell or Tcl, where a numeric string doesn?t take a meaning until you assign one. The correct form is: ibase=A /* needed only if ibase might not be 10 at this point */ obase=A /* ditto */ obase=16 /* means 16-base-10 here */ ibase=2 /* no possibility of confusion */ 10101011 Result: AB, as expected. The tricky bit is that you can?t swap the second pair of ibase and obase settings, since that would cause bc(1) to interpret obase=16 in base 2: bc(1) will clamp ?16? to 11, which in base 2 is 3-base-10.
On Mon, Aug 31, 2015 at 1:06 PM, Warren Young <wyml at etr-usa.com> wrote:> On Aug 31, 2015, at 10:05 AM, Mike - st257 <silvertip257 at gmail.com> wrote: > > > > On Mon, Aug 31, 2015 at 11:15 AM, Warren Young <wyml at etr-usa.com> wrote: > > > >> ibase=A and obase=A > > > > Not sure how this helps me with my most recent example of bin_to_hex > where > > the ibase within the define clause wasn't honored. > > That?s because your bin_to_hex function is erroneously assuming that its > input is just a string of digits that has no base interpretation, so that > it can set ibase *after* bc has already seen the value, and that this will > change the meaning of the prior input. >Explains the behavior.> > That?s just plain wrong: the prior input has already been interpreted. > You can?t wind back the clock like that. That sort of thinking only works > in a string-based language like shell or Tcl, where a numeric string > doesn?t take a meaning until you assign one. > > The correct form is: > > ibase=A /* needed only if ibase might not be 10 at this point */ > obase=A /* ditto */ > obase=16 /* means 16-base-10 here */ > ibase=2 /* no possibility of confusion */ > 10101011 > > Result: AB, as expected. >Thank you. We're in agreement, your solution _does_ work when piped or interactively. Any order does not work from a definition stanza since base10 is (apparently) not capable of being overrode with definitions. tmp]$ grep bin_to_hex ~/.bcrc #define bin_to_hex(b) { obase=16; ibase=2; return b; } define bin_to_hex(b) { ibase=A; obase=A; obase=16; ibase=2; return b; } tmp]$ echo "bin_to_hex(10101011)" | bc 9A2113 tmp]$ echo "ibase=A; obase=A; obase=16; ibase=2; 10101011" | bc AB tmp]$ echo "obase=16; ibase=2; 10101011" | bc AB> > The tricky bit is that you can?t swap the second pair of ibase and obase > settings, since that would cause bc(1) to interpret obase=16 in base 2: > bc(1) will clamp ?16? to 11, which in base 2 is 3-base-10.Agreed. Thank you, Warren. I don't believe bc is the tool for this job since define stanzas don't replicate the behavior as seen when used via piping or interactively. :-/ -- ---~~.~~--- Mike // SilverTip257 //
On Aug 31, 2015, at 11:54 AM, Mike - st257 <silvertip257 at gmail.com> wrote:> > define stanzas don't > replicate the behavior as seen when used via piping or interactively. :-/Again, it comes down to order of evaluation. You can look at the following in three stages: define bin_to_hex(b) { obase=16; ibase=2; return b; } bin_to_hex(10101011) 1. Here is a number, 10101011, which you shall interpret in base 10, since that?s the default and no one has said otherwise yet. 2. Pass that value to bin_to_hex() 3. Change the obase and ibase, then return the parameter with those new settings. You are expecting that because the define line appears first that it affects what follows, but it doesn?t affect anything until you call it for the first time. That?s clear. What I *don?t* understand is why this doesn?t work: define bin_to_hex(b) { obase=16; ibase=2; return b; } bin_to_hex(0) /* bogus call to force obase and ibase */ bin_to_hex(10101011) For some strange reason, I get 20100 out of this with both GNU and BSD bc, even though ibase=2 and obase=10 by the time of the second bin_to_hex() call. (If you?re confused about obase=10, realize that 10-base-16 is 16-base-10. :) ) Bottom line, don?t use bc for this kind of thing. It?s not the right tool for the job.