P-Adic square roots: Difference between revisions

Content added Content deleted
m (Corrected an error in a comment.)
m (Improved code.)
Line 685: Line 685:
List<List<Integer>> tests = List.of( List.of( 2, 497, 10496 ),
List<List<Integer>> tests = List.of( List.of( 2, 497, 10496 ),
List.of( 3, 15403, 26685 ),
List.of( 3, 15403, 26685 ),
List.of( 5, -19, 1) );
List.of( 7, -19, 1 ) );
for ( List<Integer> test : tests ) {
for ( List<Integer> test : tests ) {
Line 697: Line 697:
System.out.println("The rational value is " + square.convertToRational());
System.out.println("The rational value is " + square.convertToRational());
System.out.println();
System.out.println();
}
}
}
}
Line 704: Line 704:
final class PadicSquareRoot {
final class PadicSquareRoot {
/**
/**
* Create a p-adic number, with p = 'aPrime',
* Create a PadicSquareRoot number, with p = 'aPrime',
* which is the p-adic square root of the given rational 'aNumerator' / 'aDenominator'.
* which is the p-adic square root of the given rational 'aNumerator' / 'aDenominator'.
*/
*/
Line 714: Line 714:
prime = aPrime;
prime = aPrime;
digits = new ArrayList<Integer>(DIGITS_SIZE);
digits = new ArrayList<Integer>(DIGITS_SIZE);
order = 0;
order = 0;
// Process rational zero
// Process rational zero
Line 731: Line 731:
aDenominator /= prime;
aDenominator /= prime;
order -= 1;
order -= 1;
}
}
if ( ( order & 1 ) != 0 ) {
if ( ( order & 1 ) != 0 ) {
throw new AssertionError(
throw new AssertionError("Number does not have a square root in " + prime + "-adic");
aNumerator + " / " + aDenominator + " does not have a square root in " + prime + "-adic");
}
}
order >>= 1;
order >>= 1;
numerator = BigInteger.valueOf(aNumerator);
denominator = BigInteger.valueOf(aDenominator);
if ( prime == 2 ) {
if ( prime == 2 ) {
Line 749: Line 745:
}
}
/**
/**
* Return the additive inverse of this p-adic number.
* Return the additive inverse of this PadicSquareRoot number.
*/
*/
public PadicSquareRoot negate() {
public PadicSquareRoot negate() {
Line 764: Line 760:
/**
/**
* Return the product of this p-adic number and the given p-adic number.
* Return the product of this PadicSquareRoot number and the given PadicSquareRoot number.
*/
*/
public PadicSquareRoot multiply(PadicSquareRoot aOther) {
public PadicSquareRoot multiply(PadicSquareRoot aOther) {
Line 779: Line 775:
/**
/**
* Return a string representation of this p-adic as a rational number.
* Return a string representation of this PadicSquareRoot as a rational number.
*/
*/
public String convertToRational() {
public String convertToRational() {
Line 797: Line 793:
}
}


MathContext mathContext = new MathContext(PRECISION, RoundingMode.HALF_UP);
final MathContext mathContext = new MathContext(PRECISION, RoundingMode.HALF_UP);
final BigDecimal primeBig = BigDecimal.valueOf(prime);
final BigDecimal primeBig = BigDecimal.valueOf(prime);
final BigDecimal maximumPrimeBig = BigDecimal.valueOf(maximumPrime);
final BigDecimal maximumPrimeBig = BigDecimal.valueOf(maximumPrime);
Line 847: Line 843:
/**
/**
* Return a string representation of this p-adic.
* Return a string representation of this PadicSquareRoot number.
*/
*/
public String toString() {
public String toString() {
List<Integer> numbers = new ArrayList<Integer>(digits);
List<Integer> numbers = new ArrayList<Integer>(digits);
Collections.reverse(numbers);
padWithZeros(numbers);
padWithZeros(numbers);
Collections.reverse(numbers);
String numberString = numbers.stream().map(String::valueOf).collect(Collectors.joining());
String numberString = numbers.stream().map(String::valueOf).collect(Collectors.joining());
StringBuilder builder = new StringBuilder(numberString);
StringBuilder builder = new StringBuilder(numberString);
if ( order >= 0 ) {
if ( order >= 0 ) {
for ( int i = 0; i < order; i++ ) {
for ( int i = 0; i < order; i++ ) {
builder.append("0");
builder.append("0");
builder.deleteCharAt(0);
}
}
Line 865: Line 860:
} else {
} else {
builder.insert(builder.length() + order, ".");
builder.insert(builder.length() + order, ".");
while ( builder.toString().endsWith("0") ) {
builder.deleteCharAt(builder.length() - 1);
}
}
}
Line 873: Line 872:
/**
/**
* Create a p-adic, with p = 'aPrime', directly from a list of digits.
* Create a PadicSquareRoot, with p = 'aPrime', directly from a list of digits.
*
*
* With 'aOrder' = 0, the list [1, 2, 3, 4, 5] creates the p-adic ...54321.0
* With 'aOrder' = 0, the list [1, 2, 3, 4, 5] creates the p-adic ...54321.0
Line 890: Line 889:
private void squareRootEvenPrime(int aNumerator, int aDenominator) {
private void squareRootEvenPrime(int aNumerator, int aDenominator) {
if ( Math.floorMod(aNumerator * aDenominator, 8) != 1 ) {
if ( Math.floorMod(aNumerator * aDenominator, 8) != 1 ) {
throw new AssertionError(aNumerator + " / " + aDenominator + " does not have a square root in 2-adic");
throw new AssertionError("Number does not have a square root in 2-adic");
}
}


Line 898: Line 897:
// Further digits
// Further digits
final BigInteger numerator = BigInteger.valueOf(aNumerator);
final BigInteger denominator = BigInteger.valueOf(aDenominator);
while ( digits.size() < DIGITS_SIZE ) {
while ( digits.size() < DIGITS_SIZE ) {
BigInteger factor = denominator.multiply(sum.multiply(sum)).subtract(numerator);
BigInteger factor = denominator.multiply(sum.multiply(sum)).subtract(numerator);
Line 929: Line 931:
if ( firstDigit == 0 ) {
if ( firstDigit == 0 ) {
throw new IllegalArgumentException(
throw new IllegalArgumentException("Number does not have a square root in " + prime + "-adic");
aNumerator + " / " + aDenominator + " does not have a square root in " + prime + "-adic");
}
}
Line 936: Line 937:
// Further digits
// Further digits
final BigInteger numerator = BigInteger.valueOf(aNumerator);
final BigInteger denominator = BigInteger.valueOf(aDenominator);
final BigInteger firstDigitBig = BigInteger.valueOf(firstDigit);
final BigInteger firstDigitBig = BigInteger.valueOf(firstDigit);
final BigInteger primeBig = BigInteger.valueOf(prime);
final BigInteger primeBig = BigInteger.valueOf(prime);
Line 942: Line 945:


BigInteger sum = firstDigitBig;
BigInteger sum = firstDigitBig;
for ( int i = 2; i <= DIGITS_SIZE; i++ ) {
for ( int i = 2; i < DIGITS_SIZE; i++ ) {
BigInteger nextSum =
BigInteger nextSum =
sum.subtract(coefficient.multiply(denominator.multiply(sum).multiply(sum).subtract(numerator)));
sum.subtract(coefficient.multiply(denominator.multiply(sum).multiply(sum).subtract(numerator)));
Line 996: Line 999:
private List<Integer> digits;
private List<Integer> digits;
private int order;
private int order;
private BigInteger numerator;
private BigInteger denominator;
private final int prime;
private final int prime;
Line 1,009: Line 1,010:
{{ out }}
{{ out }}
<pre>
<pre>
Number: 497 / 10496 in 2-adic
umber: 497 / 10496 in 2-adic
The two square roots are:
The two square roots are:
...0101011010110011.1101
...0101011010110011.1101
Line 1,023: Line 1,024:
The rational value is 15403 / 26685
The rational value is 15403 / 26685


Number: -19 / 1 in 5-adic
Number: -19 / 1 in 7-adic
The two square roots are:
The two square roots are:
...4441201122024440231.0
...0126260226045320643.0
...0003243322420004214.0
...6540406440621346024.0
The p-adic value is ...4444444444444444411.0
The p-adic value is ...6666666666666666642.0
The rational value is -19 / 1
The rational value is -19 / 1
</pre>
</pre>