回答編集履歴

2

追加

2016/06/25 00:44

投稿

Chironian
Chironian

スコア23272

test CHANGED
@@ -131,3 +131,117 @@
131
131
  unsined と intの演算は、intがunsignedへ変換されます。intをunsigendへ変換する時、intが負ならunsignedの最大値+1を加えて、intが2の補数表現でなくても2の補数表現の時と同じ結果になるよう定義されているようです。
132
132
 
133
133
 
134
+
135
+ ---
136
+
137
+ 【更に追加】
138
+
139
+ returnの計算に処理系依存が入ってましたので修正しました。
140
+
141
+ ついでにマクロを使ってC++11でも多少みやすくしました。(本音:C++14までメンテするのは面倒)
142
+
143
+
144
+
145
+ ```C++
146
+
147
+ #include <iostream>
148
+
149
+ #include <type_traits>
150
+
151
+ #include <limits>
152
+
153
+ #include <typeinfo>
154
+
155
+
156
+
157
+ template<typename T>
158
+
159
+ constexpr typename std::make_signed<T>::type removeExcess(T value)
160
+
161
+ {
162
+
163
+ typedef typename std::make_signed<T>::type Signed;
164
+
165
+ #define LIMIT (static_cast<T>(std::numeric_limits<Signed>::max())+1)
166
+
167
+ return (LIMIT < value)?(value-LIMIT):(static_cast<Signed>(value)-std::numeric_limits<Signed>::max()-1);
168
+
169
+ }
170
+
171
+
172
+
173
+ template<bool con, typename T> using enable_if_t = typename std::enable_if<con, T>::type;
174
+
175
+
176
+
177
+ template<typename T, enable_if_t<std::is_unsigned<T>::value, std::nullptr_t> = nullptr>
178
+
179
+ constexpr T a(T min, T max, T n)
180
+
181
+ {
182
+
183
+ return (n < min)
184
+
185
+ ? a(min, max, n + (max - min + 1) * ((min - n) / (max - min + 1) + 1))
186
+
187
+ : (n - min) % (max - min + 1) + min;
188
+
189
+ }
190
+
191
+
192
+
193
+ template<typename T, enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, std::nullptr_t> = nullptr>
194
+
195
+ constexpr T a(T min, T max, T n)
196
+
197
+ {
198
+
199
+ #if 0 // original
200
+
201
+ return ((n - min) % (max - min + 1) + max - min + 1) % (max - min + 1) + min;
202
+
203
+ #else
204
+
205
+ typedef typename std::make_unsigned<T>::type Unsigned;
206
+
207
+ #define N (static_cast<Unsigned>(std::numeric_limits<T>::max())+1+n)
208
+
209
+ #define MIN (static_cast<Unsigned>(std::numeric_limits<T>::max())+1+min)
210
+
211
+ #define MAX (static_cast<Unsigned>(std::numeric_limits<T>::max())+1+max)
212
+
213
+ #define MOD (MAX - MIN + 1)
214
+
215
+ return (MOD == 0)?n:removeExcess(a(MIN, MAX, N));
216
+
217
+ #endif
218
+
219
+ }
220
+
221
+
222
+
223
+ int main()
224
+
225
+ {
226
+
227
+ std::cout << a(-100, 100, 12) << "\n";
228
+
229
+ std::cout << a( 100, 200, 12) << "\n";
230
+
231
+ std::cout << a(-200, -100, -99) << "\n";
232
+
233
+ std::cout << a(-200, -100, 12) << "\n";
234
+
235
+ std::cout << a(std::numeric_limits<int>::min(), 1000, 12) << "\n";
236
+
237
+ std::cout << a(std::numeric_limits<int>::min(), std::numeric_limits<int>::max(), 12) << "\n";
238
+
239
+
240
+
241
+ return 0;
242
+
243
+ }
244
+
245
+ ```
246
+
247
+

1

追加

2016/06/25 00:44

投稿

Chironian
Chironian

スコア23272

test CHANGED
@@ -111,3 +111,23 @@
111
111
  }
112
112
 
113
113
  ```
114
+
115
+
116
+
117
+ ---
118
+
119
+ 【追加】
120
+
121
+ 書き忘れてました。下駄を履かせればOKと思う根拠は下記です。
122
+
123
+
124
+
125
+ [少し詳しい型変換の説明](http://www9.plala.or.jp/sgwr-t/detail/TypeConversion.html)をみてます。「JIS X 3010 プログラム言語C」を参照していると書かれているので、規格的に大丈夫と期待。
126
+
127
+
128
+
129
+ 符号なし整数と符号付き整数の演算は定義されてます。
130
+
131
+ unsined と intの演算は、intがunsignedへ変換されます。intをunsigendへ変換する時、intが負ならunsignedの最大値+1を加えて、intが2の補数表現でなくても2の補数表現の時と同じ結果になるよう定義されているようです。
132
+
133
+