Как сделать «работающее» повторяющееся десятичное представление рационального числа? - PullRequest
12 голосов
/ 05 марта 2011

Я выяснил, как отобразить повторяющуюся часть повторяющейся десятичной дроби, используя OverBar.

repeatingDecimal на самом деле не работает как повторяющаяся десятичная дробь. Я хотел бы сделать его вариант, который выглядит и ведет себя как повторяющаяся десятичная дробь.


Вопрос

Как я могу заставить работать с повторением десятичного представления (возможно, используя Interpretation[])?


Фон

Пожалуйста, извините, если я бродю. Это мой первый вопрос, и я хотел уточнить, что я имею в виду.

Следующее «нарисует» повторяющийся десятичный знак.

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]

отображает правильно повторяющуюся десятичную дробь (показана здесь как картинка, так что появляется OverBar).

Repeating decimal displayed

Если заглянуть под капот, это действительно просто самозванец, изображение повторяющейся десятичной дроби ...

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

Конечно, он не ведет себя как число:

% + 24/31

fraction plus repeating decimal

Я бы хотел, чтобы дополнение принесло: 1


Редактировать: очищенная версия повторения десятичного

Леонид показал, как обернуть Format вокруг рутины и предоставить повышающие значения для добавления и умножения повторяющихся десятичных знаков. Очень полезно! Мне понадобится некоторое время, чтобы освоиться со значениями вверх и вниз.

Ниже следует упрощенная версия кода, предложенная Mr.Wizard. Я установил OverBar над каждой повторяющейся цифрой, чтобы разрешить разрыв строки. (Один OverBar над строкой выглядит аккуратнее, но не может сломаться при достижении правого поля экрана.)

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

В таблице ниже показан некоторый вывод из 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}]}]

enter image description here


Проверка решения: Работа с повторяющимися десятичными числами

Теперь давайте проверим сложение и умножение повторяющихся десятичных знаков:

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]]

repeating decimal addition and multiplication

Таким образом, сложение и умножение повторяющихся десятичных знаков работают по желанию. Power также работает нормально.

Обратите внимание, что 168/961 занимает 465 знаков справа от десятичной точки. После этого он начинает повторяться. Результаты совпадают с N[168/961, 465], за исключением OverBar, хотя разрывы строк происходят в разных местах. И, как и следовало ожидать, это соответствует следующему:

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

465 digits


Некоторые эффекты обертки Format [] в поведении N [] при суммировании повторяющихся десятичных знаков

Mr.Wizard предположил, что оболочка Format является излишней для случаев целых чисел и вещественных чисел.

Давайте рассмотрим следующие два дополнения

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

ведут себя в четырех разных случаях:

Случай 1 : результаты, когда Format обернуты вокруг повторяющихся десятичных чисел для вещественных чисел и целых чисел, при этом значения ON

Case 1

Как и ожидалось, первое сложение дает целое число, второе - десятичное.


Случай 2 : Результаты, когда Format НЕ обернуты вокруг повторяющихся десятичных чисел для вещественных и целых чисел, но значения up равны ON

Case 2

Оболочка Format для вещественных чисел и целых чисел не влияет на имеющиеся дополнения.


Случай 3 : Результаты, когда Format обернут вокруг повторяющихся десятичных чисел для вещественных и целых чисел, но значения up равны OFF

Case 3

Если значения up выключены, Format предотвращает добавление.


Случай 4 : Результаты, когда Format НЕ обернуты вокруг повторяющихся десятичных чисел для вещественных чисел и целых значений, а значения OFF

Case 4

Если значения повышения ВЫКЛ и Формат` НЕ обернуты вокруг повторяющихся десятичных чисел для вещественных и целых чисел, второе добавление работает, как и ожидалось.

Все больше причин для удаления оболочки формата для случая вещественных чисел и чисел.


У кого-нибудь есть замечания по поводу различных результатов в случаях 3 и 4?

Ответы [ 2 ]

10 голосов
/ 05 марта 2011

Вы не должны были давать repeatingDecimal DownVaues, а 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]]]

Затем вы также можете указать UpValues для интеграции с общими функциями,например:

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

Затем, например,

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

Out[146]= 1

Вы можете распространить этот подход на другие общие функции, с которыми вам может потребоваться работать repeatingDecimal.

2 голосов
/ 05 марта 2011

Вот возможный рефакторинг вашего обновленного кода.Я думаю, что это работает на этот раз (пальцы скрещены).Если вам не нужна цветная подсветка, вы можете пропустить ~Style~ и остальную часть этой строки.

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];

Я оставлю эту старую версию здесь для справки, но сейчас я делаю измененияВопрос сообщества вики.

...