LMCAS
Lamina Computer Algebra System
Toggle main menu visibility
载入中...
搜索中...
未找到
rational_parsing.cpp
浏览该文件的文档.
1
#include "
rational.hpp
"
2
#include <cctype>
3
#include <stdexcept>
4
5
namespace
LMCAS
{
6
namespace
{
7
8
class
RationalLiteral
{
9
public
:
10
std::string
integer_digits
;
11
std::string
fractional_digits
;
12
std::string
repeating_digits
;
13
bool
negative
=
false
;
14
std::int64_t
exponent
= 0;
15
16
RationalLiteral
(
const
std::string& text, std::size_t max_bytes,
17
std::size_t max_scale) :
text_
(text) {
18
if
(text.empty())
throw
std::invalid_argument(
"Rational literal is empty"
);
19
if (text.size() > max_bytes) {
20
throw std::length_error(
"Rational literal exceeds safety limit"
);
21
}
22
negative
=
read_sign
();
23
if
(
pos_
== text.size()) {
24
throw std::invalid_argument(
"Rational literal has no digits"
);
25
}
26
read_digits
(
integer_digits
);
27
const
bool
has_decimal_point =
pos_
< text.size() && text[
pos_
] ==
'.'
;
28
if
(has_decimal_point) {
29
++
pos_
;
30
read_digits
(
fractional_digits
);
31
}
32
read_repeating_digits
(has_decimal_point);
33
if
(
integer_digits
.empty() &&
fractional_digits
.empty()) {
34
throw
std::invalid_argument(
"Rational literal has no digits"
);
35
}
36
exponent
=
read_exponent
(max_scale);
37
if
(
pos_
!= text.size()) {
38
throw
std::invalid_argument(
"Invalid character in Rational literal"
);
39
}
40
if
(
integer_digits
.empty())
integer_digits
=
"0"
;
41
}
42
43
private
:
44
const
std::string&
text_
;
45
std::size_t
pos_
= 0;
46
47
bool
read_sign
() {
48
if
(
pos_
==
text_
.size() || (
text_
[
pos_
] !=
'+'
&&
text_
[
pos_
] !=
'-'
)) {
49
return
false
;
50
}
51
return
text_
[
pos_
++] ==
'-'
;
52
}
53
54
void
read_digits
(std::string& output) {
55
while
(
pos_
<
text_
.size() &&
56
std::isdigit(
static_cast<
unsigned
char
>
(
text_
[
pos_
]))) {
57
output.push_back(
text_
[
pos_
++]);
58
}
59
}
60
61
void
read_repeating_digits
(
bool
has_decimal_point) {
62
if
(
pos_
==
text_
.size() ||
text_
[
pos_
] !=
'('
)
return
;
63
if
(!has_decimal_point) {
64
throw
std::invalid_argument(
"Repeating decimal section requires a decimal point"
);
65
}
66
++
pos_
;
67
read_digits
(
repeating_digits
);
68
if
(
repeating_digits
.empty() ||
pos_
>=
text_
.size() ||
text_
[
pos_
] !=
')'
) {
69
throw
std::invalid_argument(
"Invalid repeating decimal section"
);
70
}
71
++
pos_
;
72
}
73
74
std::int64_t
read_exponent
(std::size_t max_scale) {
75
if
(
pos_
==
text_
.size() || (
text_
[
pos_
] !=
'e'
&&
text_
[
pos_
] !=
'E'
)) {
76
return
0;
77
}
78
++
pos_
;
79
const
bool
exponent_negative =
read_sign
();
80
if
(
pos_
==
text_
.size() ||
81
!std::isdigit(
static_cast<
unsigned
char
>
(
text_
[
pos_
]))) {
82
throw
std::invalid_argument(
"Rational exponent has no digits"
);
83
}
84
const
std::int64_t
value
=
read_exponent_magnitude
(max_scale);
85
return
exponent_negative ? -
value
:
value
;
86
}
87
88
std::int64_t
read_exponent_magnitude
(std::size_t max_scale) {
89
std::int64_t
value
= 0;
90
while
(
pos_
<
text_
.size() &&
91
std::isdigit(
static_cast<
unsigned
char
>
(
text_
[
pos_
]))) {
92
const
int
digit =
text_
[
pos_
++] -
'0'
;
93
if
(
value
>
static_cast<
std::int64_t
>
(max_scale / 10) ||
94
value
* 10 + digit >
static_cast<
std::int64_t
>
(max_scale)) {
95
throw
std::length_error(
"Rational exponent exceeds safety limit"
);
96
}
97
value
=
value
* 10 + digit;
98
}
99
return
value
;
100
}
101
};
102
103
}
104
105
Rational::Rational(
const
std::string&
num
) : Rational() {
106
const
RationalLiteral
literal(
num
, max_literal_bytes, max_decimal_scale);
107
const
std::string non_repeating = literal.integer_digits + literal.fractional_digits;
108
numerator = BigInt(non_repeating);
109
denominator
= pow10(literal.fractional_digits.size());
110
111
if
(!literal.repeating_digits.empty()) {
112
const
BigInt repeat_scale = pow10(literal.repeating_digits.size());
113
const
BigInt repeat_factor = repeat_scale - BigInt(1);
114
numerator = numerator * repeat_factor + BigInt(literal.repeating_digits);
115
denominator
*= repeat_factor;
116
}
117
118
if
(literal.exponent > 0) {
119
numerator *= pow10(
static_cast<
std::size_t
>
(literal.exponent));
120
}
else
if
(literal.exponent < 0) {
121
denominator
*= pow10(
static_cast<
std::size_t
>
(-literal.exponent));
122
}
123
if
(literal.negative) numerator = -numerator;
124
simplify
();
125
}
126
127
}
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::read_repeating_digits
void read_repeating_digits(bool has_decimal_point)
定义
rational_parsing.cpp:61
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::text_
const std::string & text_
定义
rational_parsing.cpp:44
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::pos_
std::size_t pos_
定义
rational_parsing.cpp:45
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::RationalLiteral
RationalLiteral(const std::string &text, std::size_t max_bytes, std::size_t max_scale)
定义
rational_parsing.cpp:16
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::exponent
std::int64_t exponent
定义
rational_parsing.cpp:14
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::repeating_digits
std::string repeating_digits
定义
rational_parsing.cpp:12
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::read_sign
bool read_sign()
定义
rational_parsing.cpp:47
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::read_exponent_magnitude
std::int64_t read_exponent_magnitude(std::size_t max_scale)
定义
rational_parsing.cpp:88
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::read_exponent
std::int64_t read_exponent(std::size_t max_scale)
定义
rational_parsing.cpp:74
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::negative
bool negative
定义
rational_parsing.cpp:13
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::read_digits
void read_digits(std::string &output)
定义
rational_parsing.cpp:54
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::integer_digits
std::string integer_digits
定义
rational_parsing.cpp:10
LMCAS::anonymous_namespace{rational_parsing.cpp}::RationalLiteral::fractional_digits
std::string fractional_digits
定义
rational_parsing.cpp:11
LMCAS::polynomial_solver_detail::num
std::shared_ptr< SymbolicExpr > num(int value)
定义
solve_polynomial_normalization.cpp:20
LMCAS
定义
assumption.hpp:11
LMCAS::simplify
ExprResult simplify(const ExprPtr &expression, ComputationContext &context)
定义
expr_transform.cpp:18
LMCAS::value
const std::string const ExprPtr & value
定义
expr.hpp:293
LMCAS::denominator
const ExprPtr & denominator
定义
expr.hpp:200
rational.hpp
精确有理数 Rational,基于 BigInt 分子/分母表示,自动约分。
src
rational_parsing.cpp
生成于
, 为 LMCAS使用
1.18.0