问题
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