22
22
#include < iostream>
23
23
#include < sstream>
24
24
#include < string>
25
+ #include < map>
25
26
using namespace std ;
26
27
28
+
27
29
/*
28
30
* Be careful the following cases:
29
31
*
@@ -41,124 +43,54 @@ using namespace std;
41
43
* > 1/17 = 0.(0588235294117647)
42
44
*/
43
45
44
-
45
- // Notes:
46
- // > check 3 times repeated-decimail numbers
47
- // > using c-style string for performance
48
- bool checkRepeat (string &dec) {
49
-
50
- size_t dot = dec.find (' .' ) + 1 ;
51
- const char *p = dec.c_str () + dot ;
52
-
53
- // for case: 0.000
54
- if (atoi (p) ==0 ) return false ;
55
-
56
- // check 3 times repeated string
57
- size_t len = dec.size ();
58
- // static string s1, s2, s3;
59
- for (int i=2 ; i<=(len-dot)/3 ; i++) {
60
- int j=0 ;
61
- const char *p1 = dec.c_str ()+len - i;
62
- const char *p2 = dec.c_str ()+len - i*2 ;
63
- const char *p3 = dec.c_str ()+len - i*3 ;
64
- for (; j<i; j++, p1++, p2++, p3++){
65
- if (*p1!=*p2 || *p1 != *p3){
66
- break ;
67
- }
68
- }
69
- if ( i == j) {
70
- dec.erase (dec.end ()-i*2 , dec.end ());
71
- dec.insert (dec.end ()-i,' (' );
72
- dec.push_back (' )' );
73
- return true ;
74
- }
75
- }
76
- return false ;
77
- }
78
-
79
- /*
80
- * 0.16
81
- * -------
82
- *6 ) 1.00
83
- * 0
84
- * -
85
- * 1 0 <-- Remainder=1, mark 1 as seen at position=0.
86
- * - 6
87
- * ---
88
- * 40 <-- Remainder=4, mark 4 as seen at position=1.
89
- * - 36
90
- * ---
91
- * 4 <-- Remainder=4 was seen before at position=1, so the fractional part which is 16 starts repeating at position=1 => 1(6).
92
- */
93
-
94
46
string fractionToDecimal (int numerator, int denominator) {
95
47
string result;
96
48
// deal with the `ZERO` cases
97
49
if (denominator == 0 ){ return result; }
98
50
if (numerator == 0 ) { return " 0" ; }
99
-
51
+
100
52
// using long long type make sure there has no integer overflow
101
53
long long n = numerator;
102
54
long long d = denominator;
103
55
104
56
// deal with negtive cases
105
- int sign = 1 ;
106
- if ( n < 0 ) {
107
- n = -n;
108
- sign = -sign;
109
- }
110
- if ( d < 0 ) {
111
- d = -d;
112
- sign = -sign;
113
- }
114
-
115
- if (sign < 0 ){
57
+ bool sign = ((float )numerator/denominator >= 0 );
58
+ if ( n < 0 ){ n = -n; }
59
+ if ( d < 0 ){ d = -d; }
60
+ if (sign == false ){
116
61
result.push_back (' -' );
117
62
}
118
63
119
- // real work
120
- long long remainder = 0 ;
121
- long long division = 0 ;
122
- bool point = false ;
123
-
124
- while ( n != 0 ) {
125
-
126
- division = n / d;
127
- remainder = n % d;
128
-
129
- if (division >=10 ){
130
- ostringstream oss;
131
- oss << division;
132
- result += oss.str ();
133
- }else {
134
- result.push_back ( division + ' 0' );
135
- }
64
+ long long remainder = n % d;
65
+
6D40
long long division = n / d;
66
+ ostringstream oss;
67
+ oss << division;
68
+ result += oss.str ();
69
+ if (remainder == 0 ){
70
+ return result;
71
+ }
72
+ // remainder has value, the result is a float
73
+ result.push_back (' .' );
136
74
137
- if ( point == false && remainder != 0 ){
138
- result. push_back ( ' . ' );
139
- point = true ;
140
- }
75
+ // using a map to recorder all of reminders and it's position.
76
+ // if the reminder appeared before, which means the repeated loop begin.
77
+ // In C++11, it's better to use unordered_map
78
+ map< long long , int > rec;
141
79
142
- // deal with case only have one number repeated. e.g. 1/3 = 0.3333
143
- if ( point == true && n == remainder * 10 ) {
144
- result.insert (result.end ()- 1 , ' (' );
80
+ for ( int pos=result. size (); remainder!= 0 ; pos++, remainder=(remainder* 10 )%d ) {
81
+ if (rec. find (remainder) != rec. end () ) {
82
+ result.insert (result.begin ()+rec[remainder] , ' (' );
145
83
result.push_back (' )' );
146
- break ;
84
+ return result ;
147
85
}
148
-
149
- // deal with the case which have multiple number repeated. e.g. 25/99 = 0.252525...
150
- if (checkRepeat (result) == true ){
151
- break ;
152
- }
153
-
154
-
155
- n = remainder * 10 ;
156
-
86
+ rec[remainder] = pos;
87
+ result.push_back ((remainder*10 )/d + ' 0' );
157
88
}
158
89
159
90
return result;
160
91
}
161
92
93
+
162
94
void test (int num, int deno)
163
95
{
164
96
cout << " numerator: " << num << " \t denominator: " << deno << " \t result: " << fractionToDecimal (num, deno) << endl;
0 commit comments