P-Adic numbers, basic: Difference between revisions

m
Improbved code.
m (Improved coding.)
m (Improbved code.)
 
(3 intermediate revisions by the same user not shown)
Line 52:
 
=={{header|C++}}==
This example displays p-adic numbers in standard mathematical format, consisting of a possibly infinite list of digits extending leftwards from the p-adic point. Answersp-adic numbers are given corrrect to O(prime^40) and rational reconstructions are accurate to O(prime^20).
<syntaxhighlight lang="c++">
#include <cmath>
Line 93:
class P_adic {
public:
// Create a P-adicP_adic number, with p = 'prime', from the given rational 'numerator' / 'denominator'.
P_adic(const uint32_t& prime, int32_t numerator, int32_t denominator) : prime(prime) {
if ( denominator == 0 ) {
throw std::invalid_argument("Denominator cannot be zero");
}
 
Line 103:
// Process rational zero
if ( numerator == 0 ) {
digits.assign(DIGITS_SIZE, 0);
order = ORDER_MAX;
return;
}
 
// Remove multiples of 'prime' and adjust the order of the P-adicP_adic number accordingly
while ( modulo_prime(numerator) == 0 ) {
numerator /= static_cast<int32_t>(prime);
Line 118 ⟶ 119:
}
 
// Standard calculation of P-adicP_adic digits
const uint64_t inverse = modulo_inverse(denominator);
while ( digits.size() < DIGITS_SIZE ) {
Line 141 ⟶ 142:
}
 
// Return the sum of this P-adicP_adic number with the given P-adicP_adic number.
P_adic add(P_adic other) {
if ( prime != other.prime ) {
throw std::invalid_argument("Cannot add p-adic's with different primes");
}
 
Line 151 ⟶ 152:
std::vector<uint32_t> result;
 
// Adjust the digits so that the P-adicP_adic points are aligned
for ( int32_t i = 0; i < -order + other.order; ++i ) {
other_digits.insert(other_digits.begin(), 0);
Line 172 ⟶ 173:
}
 
// Return the Rational representation of this P-adicP_adic number.
Rational convert_to_rational() {
std::vector<uint32_t> numbers = digits;
 
// Zero
if ( numbers.empty() || all_zero_digits(numbers) ) {
return Rational(1, 0);
}
Line 227 ⟶ 228:
}
 
// Return a string representation of this p-adicP_adic number.
std::string to_string() {
std::vector<uint32_t> numbers = digits;
while ( digits.size() > PRECISION ) {
pad_with_zeros(digitsnumbers);
digits.pop_back();
}
pad_with_zeros(digits);
 
std::string result = "";
for ( int64_t i = digitsnumbers.size() - 1; i >= 0; --i ) {
result += std::to_string(digits[i]);
}
Line 242 ⟶ 241:
for ( int32_t i = 0; i < order; ++i ) {
result += "0";
result.erase(result.begin());
}
 
Line 248 ⟶ 246:
} else {
result.insert(result.length() + order, ".");
 
while ( result[result.length() - 1] == '0' ) {
result = result.erasesubstr(0, result.beginlength() - 1);
}
}
 
return " ..." + result.substr(result.length() - PRECISION - 1);
}
 
private:
/**
* Create a P-adicP_adic, with p = 'prime', directly from a vector of digits.
*
* WithFor example: with 'order' = 0, the vector [1, 2, 3, 4, 5] creates the p-adic ...54321.0,
* 'order' > 0 shifts the vector 'order' places to the left and
* 'order' < 0 shifts the vector 'order' places to the right.
Line 265 ⟶ 267:
}
 
// Transform the given vector of digits representing a p-adicP_adic number
// into a vector which represents the negation of the p-adicP_adic number.
void negate_digits(std::vector<uint32_t>& numbers) {
numbers[0] = modulo_prime( prime - numbers[0] ) % prime;
for ( uint64_t i = 1; i < numbers.size(); ++i ) {
numbers[i] = prime - 1 - numbers[i];
Line 277 ⟶ 279:
uint32_t modulo_inverse(const uint32_t& number) const {
uint32_t inverse = 1;
while ( modulo_prime( inverse * number ) % prime != 1 ) {
inverse += 1;
}
Line 289 ⟶ 291:
}
 
// The given vector is padded on the right by zeros up to a maximum length of 'PRECISIONDIGITS_SIZE'.
void pad_with_zeros(std::vector<uint32_t>& vector) {
while ( vector.size() < PRECISIONDIGITS_SIZE ) {
vector.emplace_back(0);
}
Line 344 ⟶ 346:
 
P_adic sum = padic_one.add(padic_two);
std::cout << "sum => " << sum.to_string() << std::endl;
std::cout << "Rational = " << sum.convert_to_rational().to_string() << std::endl;
std::cout << std::endl;
Line 364 ⟶ 366:
3-adic numbers:
-2 / 87 => ...101020111222001212021110002210102011122.2
4 / 97 => ...1022220111100202001010001200002111122021022220111100202001010001200002111122021.0
sum => ...201011000022210220101111202212220210220.2
Rational = 154 / 8439
 
7-adic numbers:
5 / 8 => ...2424242424242424242424242424242424242425424242424242424242424242424242424242425.0
353 / 30809 => ...1560462505550343461155520004023663643455560462505550343461155520004023663643455.0
sum => ...4315035233123101033613062431266421216213315035233123101033613062431266421216213.0
Rational = 156869 / 246472
</pre>
Line 1,686 ⟶ 1,688:
 
=={{header|Java}}==
This example displays p-adic numbers in standard mathematical format, consisting of a possibly infinite list of digits extending leftwards from the p-adic point. Answersp-adic numbers are given correct to O(prime^40) and the rational reconstruction is correct to O(prime^20).
<syntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
 
public final class PAdicNumbersBasic {
 
Line 1,814 ⟶ 1,821:
// Zero
if ( numbers.isEmpty() || allZeroDigits(numbers) ) {
return new Rational(0, 1);
}
Line 1,867 ⟶ 1,874:
* Return a string representation of this p-adic.
*/
public String toString() {
List<Integer> numbers = new ArrayList<Integer>(digits);
while ( digits.size() > PRECISION ) {
padWithZeros(digitsnumbers);
digits.removeLast();
Collections.reverse(numbers);
}
String numberString = numbers.stream().map(String::valueOf).collect(Collectors.joining());
padWithZeros(digits);
StringBuilder builder = new StringBuilder(numberString);
StringBuilder builder = new StringBuilder();
for ( int i = digits.size() - 1; i >= 0; i-- ) {
builder.append(digits.get(i));
}
if ( order >= 0 ) {
for ( int i = 0; i < order; i++ ) {
builder.append("0");
builder.deleteCharAt(0);
}
Line 1,887 ⟶ 1,889:
} else {
builder.insert(builder.length() + order, ".");
while ( builder.toString().endsWith("0") ) {
builder.deleteCharAt(0builder.length() - 1);
}
}
return " ..." + builder.toString().substring(builder.length() - PRECISION - 1);
}
Line 1,904 ⟶ 1,910:
prime = aPrime;
digits = new ArrayList<Integer>(aDigits);
padWithZeros(digits);
order = aOrder;
}
Line 1,925 ⟶ 1,930:
*/
private void negateList(List<Integer> aDigits) {
aDigits.set(0, Math.floorMod( prime - aDigits.get(0), prime) % prime);
for ( int i = 1; i < aDigits.size(); i++ ) {
aDigits.set(i, prime - 1 - aDigits.get(i));
Line 1,956 ⟶ 1,961:
*/
private static void padWithZeros(List<Integer> aList) {
while ( aList.size() < PRECISIONDIGITS_SIZE ) {
aList.addLast(0);
}
Line 2,030 ⟶ 2,035:
 
7-adic numbers:
5 / 8 => ...2424242424242424242424242424242424242425424242424242424242424242424242424242425.0
353 / 30809 => ...1560462505550343461155520004023663643455560462505550343461155520004023663643455.0
sum => ...4315035233123101033613062431266421216213315035233123101033613062431266421216213.0
Rational = 156869 / 246472
</pre>
897

edits