How can I make a “working” repeating decimal representation of a rational number?

╄→尐↘猪︶ㄣ 提交于 2020-01-09 19:27:28

问题


I've figured out how to display the repeating part of a repeating decimal using OverBar.

repeatingDecimal doesn't actually work as a repeating decimal. I'd like to make a variation of it that looks and behaves like a repeating decimal.


Question

How could I make a working repeating decimal representation (possibly using Interpretation[])?


Background

Please excuse me if I ramble. This is my first question and I wanted to be clear about what I have in mind.

The following will "draw" a repeating decimal.

repeatingDecimal[q2_] :=
 Module[{a},
  a[{{nr__Integer}, pt_}] := 
   StringJoin[
    Map[ToString, 
     If[pt > -1, Insert[{nr}, ".", pt + 1], 
      Join[{"."}, Table["0", {Abs[pt]}], {nr}]]]];
  (* repeating only *)

  a[{{{r__Integer}}, pt_}] := 
   Row[{".", OverBar@StringJoin[Map[ToString, {r}]]}];

  (* One or more non-repeating; 
  more than one repeating digit KEEP IN THIS ORDER!! *)
  a[{{nr__, {r__}}, pt_}] := 
   Row[{StringJoin[
      Map[ToString, 
       If[pt > -1, Insert[{nr}, ".", pt + 1], 
        Join[{"."}, Table["0", {Abs[pt]}], {nr}]]]], 
     OverBar@StringJoin[Map[ToString, {r}]]}];
  (* One or more non-repeating; one repeating digit *)

  a[{{nr__, r_Integer}, pt_}] := 
   Row[{StringJoin[Map[ToString, {nr}]], ".", 
     OverBar@StringJoin[Map[ToString, r]]}];
  a[RealDigits[q2]]]

So

repeatingDecimal[7/31]

displays a repeating decimal properly (shown here as a picture so that the OverBar appears).

Looking under the hood, it's really just an imposter, an image of a repeating decimal ...

In[]:= repeatingDecimal[7/31]//FullForm
Out[]:= Row[List[".",OverBar["225806451612903"]]]

Of course, it doesn't behave like a number:

% + 24/31

I'd like the addition to yield: 1


Edit: A cleaned up version of repeatingDecimal

Leonid showed how to wrap Format around the routine and to supply up-values for adding and multiplying repeated decimals. Very helpful! It will take some time for me to be comfortable with up and down values.

What follows below is essentially the streamlined version of the code suggested by Mr.Wizard. I set the OverBar above each repeating digit to allow line-breaking. (A single OverBar above Row looks tidier but cannot break when the right screen-margin is reached.)

ClearAll[repeatingDecimal]

repeatingDecimal[n_Integer | n_Real] := n

Format[repeatingDecimal[q_Rational]] := Row @ Flatten[
   {IntegerPart@q, ".", RealDigits@FractionalPart@q} /.
    {{nr___Integer, r_List: {}}, pt_} :> {Table[0, {-pt}], nr, OverBar /@ r}
  ]

repeatingDecimal[q_] + x_ ^:= q + x
repeatingDecimal[q_] * x_ ^:= q * x
repeatingDecimal[q_] ^ x_ ^:= q ^ x

The table below shows some output from repeatingDecimal:

n1 = 1; n2 = 15; ClearAll[i, k, r];
TableForm[Table[repeatingDecimal[i/j], {i, n1, n2}, {j, n1, n2}], 
TableHeadings -> {None, Table[("r")/k, {k, n1, n2}]}]


Checking the solution: Operating with repeating decimals

Let's now check the addition and multiplication of repeating decimals:

a = repeatingDecimal[7/31];
b = repeatingDecimal[24/31];
Print["a = ", a]
Print["b = ", b]
Print["a + b = ", a, " + ", b, " = ", a + b]
Print["7/31 \[Times] 24/31 = " , (7/31)* (24/31)]
Print["a\[Times]b = ", a*b, " = \n", repeatingDecimal[a*b]]
Print[N[168/961, 465]]

So addition and multiplication of repeating decimals work as desired. Power also appears to work properly.

Notice that 168/961 occupies 465 places to the right of the decimal point. After that, it starts to repeat. The results match those of N[168/961, 465], except for the OverBar, although line-breaks occur at different places. And, as is to be expected, this jibes with the following:

digits = RealDigits[168/961]
Length[digits[[1, 1]]]


Some effects of the Format[] wrapper on the behavior of N[] in summing repeated decimals

Mr.Wizard suggested that the Format wrapper is superfluous for the cases of Integers and Reals.

Let's consider how the following two additions

repeatingDecimal[7/31] + repeatingDecimal[24/31]
N@repeatingDecimal[7/31] + N@repeatingDecimal[24/31]

behave in four different cases:

Case 1: Results when Format wrapped around repeatingDecimals for Reals and Integers and up values are ON

As expected, the first addition yields an integer, the second a decimal.


Case 2: Results when Format NOT wrapped around repeatingDecimals for Reals and Integers but up values are ON

The Format wrapper around Reals and Integers doesn't affect the additions at hand.


Case 3: Results when Format wrapped around repeatingDecimals for Reals and Integers but up values are OFF

If upvalues are OFF, Format prevents addition from happening.


Case 4: Results when Format NOT wrapped around repeatingDecimals for Reals and Integers and up values are OFF

If upvalues are OFF and Format` NOT wrapped around repeatingDecimals for Reals and Integers , the second addition works as expected.

All the more reason to remove the Format wrapper for the case of reals and integers.


Anyone have any remarks about the different outcomes in Cases 3 and 4?


回答1:


You shouldn't have given your repeatingDecimal DownVaues, but rather, FormatValues:

ClearAll[repeatingDecimal];
Format[repeatingDecimal[q2_]] := 
Module[{a}, 
 a[{{nr__Integer}, pt_}] := 
 StringJoin[
  Map[ToString, 
   If[pt > -1, Insert[{nr}, ".", pt + 1], 
  Join[{"."}, Table["0", {Abs[pt]}], {nr}]]]];
  (*repeating only*)
 a[{{{r__Integer}}, pt_}] := 
 Row[{".", OverBar@StringJoin[Map[ToString, {r}]]}];
(*One or more non-repeating;
more than one repeating digit KEEP IN THIS ORDER!!*)
a[{{nr__, {r__}}, pt_}] := 
 Row[{StringJoin[
   Map[ToString, 
    If[pt > -1, Insert[{nr}, ".", pt + 1], 
     Join[{"."}, Table["0", {Abs[pt]}], {nr}]]]], 
  OverBar@StringJoin[Map[ToString, {r}]]}];
(*One or more non-repeating;one repeating digit*)
a[{{nr__, r_Integer}, pt_}] := 
  Row[{StringJoin[Map[ToString, {nr}]], ".", 
   OverBar@StringJoin[Map[ToString, r]]}];
a[RealDigits[q2]]]

Then, you can give it also UpValues, to integrate with common functions, for example:

repeatingDecimal /: Plus[left___, repeatingDecimal[q_], right___] := left + q + right;
repeatingDecimal /: Times[left___, repeatingDecimal[q_], right___] :=  left * q * right;

Then, for example,

In[146]:= repeatingDecimal[7/31]+24/31

Out[146]= 1

You can extend this approach to other common functions which you may want to work with repeatingDecimal.




回答2:


Here is a possible refactoring of your updated code. I think it works this time (fingers crossed). If you do not need the color highlighting, you can leave off ~Style~ and the rest of that line.

ClearAll[repeatingDecimal];

Format[repeatingDecimal[n_Integer | n_Real]] := n;

Format[repeatingDecimal[q_Rational]] :=
 Row[{IntegerPart@q, ".", RealDigits@FractionalPart@q}] /.
  {{ nr___Integer, r_List:{} }, pt_} :>
   Row@Join[
      "0" ~Table~ {-pt},
      {nr},
      If[r === {}, {}, {OverBar@Row@r}]
      ] ~Style~ If[r === {}, Blue, If[{nr} === {}, Red, Gray]]

repeatingDecimal /:
  (h : Plus | Times)[left___, repeatingDecimal[q_], right___] :=
    h[left, q, right];

I will leave this older version here for reference, but I am now making edits to the Question community wiki.



来源:https://stackoverflow.com/questions/5200617/how-can-i-make-a-working-repeating-decimal-representation-of-a-rational-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!