3

This is a follow-up question to this question.

I generated a list by substituting the results of a solve[] routine and set:

sln=expression /.Solve[...];
list= SetAccuracy[N[sln],2]]

You can find the FullForm[list] further down. I was trying to parition this list into sublists with equal norms.

If you evaluate Map[Norm, list] you get {0, 1.6, 0.6, 0.6, 1.6, 1.6, 0.6, 0.6, 1.6, 0.6, 1.6} There are three sets of values for the norms.

I tried

GatherBy[SortBy[list, Norm], Norm]

and

SplitBy[SortBy[list, Norm], Norm]

And they give me different results. However, if my list2 was a list of numbers inputted by hands without any explicit accuracy, the two expressions yield equal results.

  • What is different about SplitBy[] and Gatherby[] that causes this?
  • How do accuracy and precision interplay in numerical results?

For reproduciblity purposes, I am quoting FullForm version of list variable that I performed the tests with:

FullForm[list]=     \!\(
TagBox[
StyleBox[
RowBox[{"List", "[", 
RowBox[{
RowBox[{"List", "[", 
RowBox[{"0``2.", ",", "0``2."}], "]"}], ",", 
RowBox[{"List", "[", 
RowBox[{"0.5`1.6989700043360187", ",", 
        "0.86602540378443859658830206171842291951`1.93753063169585"}],
        "]"}], ",", 
RowBox[{"List", "[", 
RowBox[{"0.5`1.6989700043360187", ",", 
RowBox[{"-", 
         "0.86602540378443859658830206171842291951`1.93753063169585"}]\
}], "]"}], ",", 
RowBox[{"List", "[", 
RowBox[{
RowBox[{"-", "1.`2."}], ",", "0``2."}], "]"}]}], "]"}],
ShowSpecialCharacters->False,
ShowStringCharacters->True,
NumberMarks->True],
FullForm]\)

and

GatherBy[SortBy[a, Norm], Norm] == SplitBy[SortBy[a, Norm], Norm]

returns False.

Shb
  • 701
  • 3
  • 10

2 Answers2

3

In the words of WReach: SameQ Is Not An Equivalence Relation

I shall take Simon Woods's concise example as a starting point:

list = SetAccuracy[{1, 1, 1.01, 1.01, 1.02, 1.02}, 2];

Gather[list]
Split[list]

{{1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}}

{{1.0, 1.0, 1.0, 1.0, 1.0, 1.0}}

Split compares elements that are side-by-side, and in that measure they are all SameQ true:

SameQ @@@ Partition[list, 2, 1]
{True, True, True, True, True}

However this does not mean that the first and last elements are SameQ true!

SameQ @@ list[[{1, -1}]]
False

SameQ is not a complete explanation for this behavior because it is possible to set an Internal`$SameQTolerance that sees the first and last elements as identical, yet have Gather return three lists:

Internal`$SameQTolerance = 3;

SameQ @@ list[[{1, -1}]]

Gather[list]
True

{{1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}}

With a sufficiently high value a single list is returned, so this is having an effect on Gather:

Internal`$SameQTolerance = 15;

Gather[list]
{{1.0, 1.0, 1.0, 1.0, 1.0, 1.0}}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
0
list = SetAccuracy[{1, 1, 1.01, 1.01, 1.02, 1.02}, 2] // Partition[#, 2] &

(*  {{1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}}  *)

To get what appears to be his desired behaviour, I think the OP should be using Round

GatherBy[SortBy[list, Norm], Norm[Round[#, .1]] &]

(*  {{{1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}}}  *)

SplitBy[SortBy[list, Norm], Norm]

(*  {{{1.0, 1.0}, {1.0, 1.0}, {1.0, 1.0}}}  *)

% === %%

True
Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198