TNB Library
TnbRealNumber.h
[詳解]
1#pragma once
11#include "TnbStr.h"
12
13
14
15#include <float.h>
16#include <math.h>
17
18
19
20//TNB Library
21namespace TNB
22{
23
24
25
78{
79public:
80
83 {
89 };
90
91private:
92
93 double m_doValue;
94 WORD m_wStatus;
95 WORD m_wParam;
96
103 static void ms_CheckValue(double value, WORD& _status)
104 {
105 if ( _status == ES_Valid )
106 {
107 if ( ::_isnan(value) != 0 )
108 {
109 //異常な値だ
110 _status = ES_Invalid;
111 }
112 else if ( ::_finite(value) == 0 )
113 {
114 //オーバーフローを入れておく
115 _status = ES_OverFlow;
116 }
117 }
118 }
119
127 static WORD ms_CalcStatus(WORD left, WORD right)
128 {
129 if ( left == ES_Empty || right == ES_Empty )
130 {
131 // 片方でもエンプティならエンプティ
132 left = ES_Empty;
133 }
134 else if ( left == ES_Invalid || right == ES_Invalid )
135 {
136 // 片方でも不正なら結果は不正
137 left = ES_Invalid;
138 }
139 else if ( left == ES_Valid )
140 {
141 //左辺が有効なら結果は右辺の状態
142 left = right;
143 }
144 else if ( right == ES_Valid )
145 {
146 //右辺が有効なら結果は左辺の状態
147 }
148 else
149 {
150 //何らかのエラーだ
151 left = ES_Invalid;
152 }
153 return left;
154 }
155
160 void m_CheckValue(void)
161 {
162 ms_CheckValue(m_doValue, m_wStatus);
163 }
164
169 CRealNumber(double value, int status, int param)
170 : m_doValue(value), m_wStatus(static_cast<WORD>(status)), m_wParam(static_cast<WORD>(param))
171 {
172 }
173
174public:
175
180 CRealNumber(void) : m_doValue(0), m_wStatus(ES_Empty), m_wParam(0)
181 {
182 }
183
189 : m_doValue(other.m_doValue), m_wStatus(other.m_wStatus), m_wParam(other.m_wParam)
190 {
191 }
192
198 CRealNumber(double value) : m_doValue(value), m_wStatus(ES_Valid), m_wParam(0)
199 {
200 m_CheckValue();
201 }
202
208 CRealNumber(int value) : m_doValue(value), m_wStatus(ES_Valid), m_wParam(0)
209 {
210 }
211
217 CRealNumber(const CStr& str) : m_doValue(0), m_wStatus(ES_Empty), m_wParam(0)
218 {
219 if ( ! str.IsEmpty() )
220 {
221 m_doValue = str.ToDouble();
222 m_wStatus = ES_Valid;
223 m_CheckValue();
224 }
225 }
226
233 {
234 m_doValue = other.m_doValue;
235 m_wStatus = other.m_wStatus;
236 m_wParam = other.m_wParam;
237 return *this;
238 }
239
246 CRealNumber& operator=(double value)
247 {
248 m_doValue = value;
249 m_wStatus = ES_Valid;
250 m_wParam = 0;
251 m_CheckValue();
252 return *this;
253 }
254
262 {
263 m_doValue = value;
264 m_wStatus = ES_Valid;
265 m_wParam = 0;
266 m_CheckValue();
267 return *this;
268 }
269
277 {
278 if ( ! str.IsEmpty() )
279 {
280 m_doValue = str.ToDouble();
281 m_wStatus = ES_Valid;
282 m_CheckValue();
283 }
284 else
285 {
286 Empty();
287 }
288 }
289
290 #ifndef _TnbDOXYGEN //Document作成用シンボル
291
292 //---------------------------------
293 //
294 // 代入系チーム
295 //
296 #define FUNCMAC2(EQ, DST, VL) \
297 CRealNumber& operator EQ (DST){ \
298 m_doValue EQ VL.m_doValue; \
299 m_wStatus = ms_CalcStatus(m_wStatus, VL.m_wStatus); \
300 m_wParam |= VL.m_wParam; \
301 m_CheckValue(); \
302 return *this; \
303 }
304
305 #define FUNCMAC1(DST, VL) \
306 FUNCMAC2( +=, DST, VL ); \
307 FUNCMAC2( -=, DST, VL ); \
308 FUNCMAC2( *=, DST, VL ); \
309 CRealNumber& operator/=(DST) { \
310 if ( VL.m_doValue != 0.0 ) { \
311 m_doValue /= VL.m_doValue; \
312 m_wStatus = ms_CalcStatus(m_wStatus, VL.m_wStatus); \
313 m_wParam |= VL.m_wParam; \
314 } else { \
315 m_doValue = 0; \
316 if ( VL.m_wStatus == ES_Empty ) { \
317 m_wStatus = ms_CalcStatus(m_wStatus, ES_Empty); \
318 } else { \
319 m_wStatus = ms_CalcStatus(m_wStatus, ES_ZeroDivied);\
320 } \
321 } \
322 m_CheckValue(); \
323 return *this; \
324 }
325
326 FUNCMAC1( const CRealNumber& value, value );
327 FUNCMAC1( double doValue, CRealNumber(doValue) );
328 FUNCMAC1( int iValue, CRealNumber(iValue) );
329
330 #undef FUNCMAC1
331 #undef FUNCMAC2
332
333 //-------------------------------------
334 //
335 // 演算の花道
336 //
337 #define FUNCMAC2(EQ, DST, VL) \
338 CRealNumber operator EQ (DST) const { \
339 CRealNumber r = *this; \
340 r EQ##= VL; \
341 return r; \
342 }
343
344 #define FUNCMAC1(DST, VL) \
345 FUNCMAC2( +, DST, VL ) \
346 FUNCMAC2( -, DST, VL ) \
347 FUNCMAC2( *, DST, VL ) \
348 FUNCMAC2( /, DST, VL )
349
350 FUNCMAC1( const CRealNumber& value, value );
351 FUNCMAC1( double doValue, CRealNumber(doValue) );
352 FUNCMAC1( int iValue, CRealNumber(iValue) );
353
354 #undef FUNCMAC1
355 #undef FUNCMAC2
356
357 #define FUNCMAC2(EQ,DST,VL) \
358 friend CRealNumber operator EQ (DST, const CRealNumber& value){ \
359 CRealNumber r = VL; \
360 r EQ##= value; \
361 return r; \
362 }//---------------------------------------------------------------
363
364 #define FUNCMAC1(DST, VL) \
365 FUNCMAC2( +, DST, VL ); \
366 FUNCMAC2( -, DST, VL ); \
367 FUNCMAC2( *, DST, VL ); \
368 FUNCMAC2( /, DST, VL );
369
370 FUNCMAC1( double doValue, doValue )
371 FUNCMAC1( int iValue, iValue )
372
373 #undef FUNCMAC1
374 #undef FUNCMAC2
375
376 //---------------------------------------------
377 //
378 // 関数
379 //
380 #define FUNCMAC1(CMD) \
381 friend CRealNumber CMD(const CRealNumber& value) { \
382 if ( value.m_wStatus == ES_Valid ) { \
383 CRealNumber r(::CMD(value.m_doValue), \
384 value.m_wStatus, value.m_wParam); \
385 r.m_CheckValue(); \
386 return r; \
387 } \
388 return CRealNumber(0, value.m_wStatus, value.m_wParam); \
389 } \
390 friend double CMD(double value) { return ::CMD(value); }
391
392 FUNCMAC1( acos );
393 FUNCMAC1( asin );
394 FUNCMAC1( atan );
395 FUNCMAC1( cos );
396 FUNCMAC1( cosh );
397 FUNCMAC1( exp );
398 FUNCMAC1( fabs );
399 FUNCMAC1( log );
400 FUNCMAC1( log10 );
401 FUNCMAC1( sin );
402 FUNCMAC1( sinh );
403 FUNCMAC1( tan );
404 FUNCMAC1( tanh );
405 FUNCMAC1( sqrt );
406 FUNCMAC1( ceil );
407 FUNCMAC1( floor );
408 FUNCMAC1( _j0 );
409 FUNCMAC1( _j1 );
410 FUNCMAC1( _y0 );
411 FUNCMAC1( _y1 );
412
413 #undef FUNCMAC1
414
415 #define FUNCMAC1(CMD, DSP, VL) \
416 friend CRealNumber CMD(const CRealNumber& value, DSP) { \
417 double d = 0; \
418 if ( value.m_wStatus == ES_Valid && VL.m_wStatus == ES_Valid ){\
419 d = ::CMD(value.m_doValue, VL.m_doValue); \
420 } \
421 CRealNumber r(d, ms_CalcStatus(value.m_wStatus, VL.m_wStatus),\
422 value.m_wParam|VL.m_wParam); \
423 r.m_CheckValue(); \
424 return r; \
425 }
426
427 #define FUNCMAC2(CMD) \
428 FUNCMAC1( CMD, const CRealNumber& value2, value2 ); \
429 FUNCMAC1( CMD, double doValue, CRealNumber(doValue) ); \
430 FUNCMAC1( CMD, int iValue, CRealNumber(iValue) ); \
431 friend double CMD(double v1, double v2) { return ::CMD(v1, v2); }
432
433 FUNCMAC2( atan2 );
434 FUNCMAC2( fmod );
435 FUNCMAC2( pow );
436 FUNCMAC2( _hypot );
437
438 #undef FUNCMAC2
439 #undef FUNCMAC1
440
441 friend CRealNumber frexp(const CRealNumber& value, int* _Y)
442 {
443 CRealNumber r(::frexp(value.m_doValue, _Y), value.m_wStatus, value.m_wParam);
444 r.m_CheckValue();
445 return r;
446 }
447
448 friend double frexp(double value, int* _Y)
449 {
450 return ::frexp(value, _Y);
451 }
452
453 friend CRealNumber _jn(int _X, const CRealNumber& value)
454 {
455 CRealNumber r(::_jn(_X, value.m_doValue), value.m_wStatus,value.m_wParam);
456 r.m_CheckValue();
457 return r;
458 }
459
460 friend double _jn(int _X, double value)
461 {
462 return ::_jn(_X, value);
463 }
464
465 friend CRealNumber ldexp(const CRealNumber& value, int iValue)
466 {
467 CRealNumber r(::ldexp(value.m_doValue, iValue), value.m_wStatus, value.m_wParam);
468 r.m_CheckValue();
469 return r;
470 }
471
472 friend double ldexp(double value, int iValue)
473 {
474 return ::ldexp(value, iValue);
475 }
476
477 friend CRealNumber modf(const CRealNumber& value, double* _Y)
478 {
479 CRealNumber r(::modf(value.m_doValue, _Y), value.m_wStatus, value.m_wParam);
480 r.m_CheckValue();
481 return r;
482 }
483
484 friend double modf(double value, double* _Y)
485 {
486 return ::modf(value, _Y);
487 }
488
489 friend CRealNumber _yn(int _X, const CRealNumber& value)
490 {
491 CRealNumber r(::_yn(_X, value.m_doValue), value.m_wStatus, value.m_wParam);
492 r.m_CheckValue();
493 return r;
494 }
495
496 friend double _yn(int _X, double value)
497 {
498 return ::_yn(_X, value);
499 }
500
501 //---------------------------------------------
502 //
503 // 比較(有)
504 //
505 #define FUNCMAC2(EQ,TY,VL) \
506 friend bool operator EQ(TY VL##1, TY VL##2) { \
507 if ( VL##1.m_wStatus != ES_Valid ){ return false; } \
508 if ( VL##2.m_wStatus != ES_Valid ){ return false; } \
509 return VL##1.m_doValue EQ VL##2.m_doValue; \
510 } \
511 friend bool operator EQ(TY VL, double d) { \
512 return operator EQ(VL, CRealNumber(d)); \
513 } \
514 friend bool operator EQ(TY VL, int d) { \
515 return operator EQ(VL, CRealNumber(d)); \
516 }
517 #define FUNCMAC1(TY, VL) \
518 friend bool operator==(TY VL##1, TY VL##2) { \
519 if ( VL##1.m_wStatus != VL##2.m_wStatus ){ return false; } \
520 if ( VL##1.m_wStatus != ES_Valid && VL##1.m_wStatus == VL##2.m_wStatus ){ return true; }\
521 return VL##1.m_doValue == VL##2.m_doValue; \
522 } \
523 friend bool operator==(TY VL, double d) { \
524 return operator==(VL, CRealNumber(d)); \
525 } \
526 friend bool operator==(TY VL, int d) { \
527 return operator==(VL, CRealNumber(d)); \
528 } \
529 friend bool operator!=(TY VL##1, TY VL##2) { \
530 return ! operator==(VL##1, VL##2); \
531 } \
532 friend bool operator!=(TY VL, double d) { \
533 return operator!=(VL, CRealNumber(d)); \
534 } \
535 friend bool operator!=(TY VL, int d) { \
536 return operator!=(VL, CRealNumber(d)); \
537 } \
538 FUNCMAC2( <, TY, VL ); \
539 FUNCMAC2( <=, TY, VL ); \
540 FUNCMAC2( >, TY, VL ); \
541 FUNCMAC2( >=, TY, VL );
542
543 FUNCMAC1( const CRealNumber&, value );
544
545 #undef FUNCMAC1
546 #undef FUNCMAC2
547
548 #endif // _TnbDOXYGEN
549
550 //------------------------------------------
551
552
558 double ToDouble(void) const
559 {
560 #ifdef _DEBUG
561 if ( m_wStatus != ES_Valid )
562 {
563 ASSERT1(false, "CRealNumber::ToDouble()", "状態が VALID(0)以外です (r=%u) 。", m_wStatus);
564 return 0;
565 }
566 #endif
567 return m_doValue;
568 }
569
575 operator double() const
576 {
577 return ToDouble();
578 }
579
585 int ToInt(void) const
586 {
587 return TNB::ToInt(ToDouble());
588 }
589
594 void Empty(void)
595 {
596 m_doValue = 0;
597 m_wStatus = ES_Empty;
598 m_wParam = 0;
599 }
600
606 bool IsValid(void) const
607 {
608 return m_wStatus == ES_Valid;
609 }
610
616 bool IsEmpty(void) const
617 {
618 return m_wStatus == ES_Empty;
619 }
620
625 EStatus GetStatus(void) const
626 {
627 return static_cast<EStatus>(m_wStatus);
628 }
629
635 void SetStatus(EStatus status)
636 {
637 m_doValue = 0;
638 m_wStatus = static_cast<WORD>(status);
639 }
640
645 WORD GetParam(void) const
646 {
647 return m_wParam;
648 }
649
655 WORD& RefParam(void)
656 {
657 return m_wParam;
658 }
659
664 void SetParam(WORD wParam)
665 {
666 m_wParam = wParam;
667 }
668
676 bool IsEqual(const CRealNumber& r) const
677 {
678 return *this == r;
679 }
680
690 bool IsAlmostEqual(const CRealNumber& r, double doDepth = 0.01) const
691 {
692 if ( m_wStatus != r.m_wStatus ){ return false; }
693 if ( m_wStatus != ES_Valid && m_wStatus == r.m_wStatus ){ return true; }
694 //TRACE2("IsAlmostEqual(%f,%f)\n",::floor(m_doValue * doDepth + 0.5) ,::floor(r.m_doValue * doDepth + 0.5));
695 return ::floor(m_doValue / doDepth + 0.5) == ::floor(r.m_doValue / doDepth + 0.5);
696 }
697
703 CStr ToString(LPCTSTR lpszFormat = NULL) const
704 {
705 CStr s;
706 switch ( m_wStatus )
707 {
708 case ES_Valid: // 有効な値を保持
709 if ( lpszFormat == NULL || lpszFormat[0] == 0 )
710 {
711 lpszFormat = _T("%f");
712 }
713 s.Format(lpszFormat, m_doValue);
714 break;
715 case ES_Empty: // 値なし
716 break;
717 case ES_Invalid: // 無効な値を保持
718 s = _T("-Invalid-");
719 break;
720 case ES_ZeroDivied: // Zero Divied状態
721 s = _T("-ZeroDivied-");
722 break;
723 case ES_OverFlow: // Overflow状態
724 s = _T("-OverFlow-");
725 break;
726 default:
727 ASSERT(false);
728 break;
729 }
730 return s;
731 }
732};
733
734
735
736}; // TNB
737
文字列管理関係のヘッダ
実数管理クラス
Definition: TnbRealNumber.h:78
CRealNumber(double value)
代入コンストラクタ
CRealNumber(void)
コンストラクタ
bool IsEmpty(void) const
[確認] EMPTY確認
int ToInt(void) const
[取得] int型取得.
void SetStatus(EStatus status)
[設定] 状態設定
bool IsEqual(const CRealNumber &r) const
[確認] 比較
double ToDouble(void) const
[取得] double型取得.
CRealNumber(const CRealNumber &other)
コピーコンストラクタ
CRealNumber & operator=(const CStr &str)
[代入] 代入
bool IsAlmostEqual(const CRealNumber &r, double doDepth=0.01) const
[確認] あいまい比較.
bool IsValid(void) const
[確認] 有効確認
CRealNumber(int value)
代入コンストラクタ
CRealNumber & operator=(double value)
[代入] 代入
@ ES_OverFlow
Overflow状態
Definition: TnbRealNumber.h:88
@ ES_Valid
有効状態
Definition: TnbRealNumber.h:84
@ ES_Empty
Empty状態
Definition: TnbRealNumber.h:85
@ ES_ZeroDivied
Zero Divied状態
Definition: TnbRealNumber.h:87
@ ES_Invalid
無効状態
Definition: TnbRealNumber.h:86
WORD GetParam(void) const
[取得] パラメータ取得
EStatus GetStatus(void) const
[確認] 状態確認
CRealNumber & operator=(int value)
[代入] 代入
void SetParam(WORD wParam)
[設定] パラメータ設定
void Empty(void)
[設定] Empty.
CStr ToString(LPCTSTR lpszFormat=NULL) const
[取得] 文字列作成
CRealNumber(const CStr &str)
代入コンストラクタ.
CRealNumber & operator=(const CRealNumber &other)
[代入] コピーオペレータ
WORD & RefParam(void)
[取得] パラメータ参照
bool IsEmpty(void) const
[確認] 空チェック
Definition: TnbStr.h:528
double ToDouble(INDEX iOffset=0) const
[取得] 数値(double)へ変換
Definition: TnbStr.h:874
void Format(const TYP *lpszFormat,...)
[代入] 書式付き文字列代入.
Definition: TnbStr.h:359
int ToInt(LPCSTR lpsz, int iBase=10)
[変換] INT変換(ASCII/SJIS用).
Definition: TnbStrLib.h:367
CRealNumber tan(const CValueDegree &d)
[計算] tan (値 = tan(角度))
CRealNumber sin(const CValueDegree &d)
[計算] sin (値 = sin(角度))
CValueDistance sqrt(const CValueArea &a)
[計算] 平方根 (距離 = √面積)
CRealNumber cos(const CValueDegree &d)
[計算] cos (値 = cos(角度))
CRealNumber cosh(const CValueDegree &d)
[計算] cosh (値 = cosh(角度))
CRealNumber sinh(const CValueDegree &d)
[計算] sinh (値 = sinh(角度))
CRealNumber tanh(const CValueDegree &d)
[計算] tanh (値 = tanh(角度))
TNB Library
Definition: TnbDoxyTitle.txt:2