NormalizeDouble을 사용하여 MT4에서 숫자 반올림 - 페이지 16

 
fxsaber :
더 이상 사용되지 않음

표준 라이브러리 에는 Granulation을 고려한 가격 정규화 기능이 있습니다.

 //+------------------------------------------------------------------+
//| Normalize price                                                  |
//+------------------------------------------------------------------+
double CSymbolInfo::NormalizePrice( const double price) const
  {
   if (m_tick_size!= 0 )
       return ( NormalizeDouble ( MathRound (price/m_tick_size)*m_tick_size,m_digits));
//---
   return ( NormalizeDouble (price,m_digits));
  }
 
Slawa :

표준 라이브러리 에는 Granulation을 고려한 가격 정규화 기능이 있습니다.

이 매우 느린 구현을 알고 있습니다. NormalizeDouble(및 도움말)을 현재 현실로 마무리하는 것이었습니다. 누구나 자신의 과립을 작성할 수 있습니다.
 
transcendreamer :
나는 이미 NormalizeDouble(new_lot-sum_lots, Lottes_Digits); 정확히 0을주지는 않지만 일종의 꼬리를 유지합니다.

변수 new_lot과 sum_lots가 같으면 그 차이는 정확히 0이 됩니다. 그러나 어떻게 계산하는지 알 수 없으며 실제로 계산에서 동일하지 않은 것으로 판명될 수 있으므로 차이가 0이 아닙니다. 다음과 같이 동일하게 수행하십시오.

NormalizeDouble (new_lot,lots_Digits) - NormalizeDouble(sum_lots,Lot_Digits).

변수가 지정된 자릿수 내에서 같으면 차이는 엄격하게 0입니다.

 
Sergei Vladimirov :

변수 new_lot과 sum_lots가 같으면 그 차이는 정확히 0이 됩니다. 그러나 어떻게 계산하는지 알 수 없으며 실제로 계산에서 동일하지 않은 것으로 판명될 수 있으므로 차이가 0이 아닙니다. 다음과 같이 동일하게 수행하십시오.

NormalizeDouble(new_lot, lot_Digits) - NormalizeDouble(sum_lots, lot_Digits).

변수가 지정된 자릿수 내에서 같으면 차이는 엄격하게 0입니다.

오 감사합니다!
 
transcendreamer :

그리고 다시 반올림에 대해 .......

상황에 따라 말해주세요 (토마토는 던지지 마세요, 저는 휴머니스트입니다),

이 변수가 있습니다:

      double delta=NormalizeDouble(new_lot-sum_lots,Lots_Digits);

      if(delta>0) delta-=OrderLots();

      if(delta<0) delta+=OrderLots();

이론적으로 델타는 초기에 정규화되며,

OrderLots는 아마도 정규화된 double을 반환해야 합니다.

하지만 가끔 드물게 2.775557561562891e-17과 같은 숫자를 얻습니다.

즉, 거의 0이지만 0은 아닙니다........

첫 번째 질문은 이것이 정상입니까?

...


자세히 다시 읽어보았습니다. 니피가는 정상이 아닙니다. NormalizeDouble 함수의 작동 방식:

  1. 전체가 눈에 띈다 - 나
  2. 소수 부분이 강조 표시됨 - F
  3. F = F * 10^자리
  4. F = F(기호에 따라 + 또는 -) 0.5
  5. F = (F의 정수 부분) / 10^자리
  6. 결과 = 나 + F
new_lot 및 sum_lots가 지정된 자릿수 내에서 동일한 경우 NormalizeDouble(new_lot - sum_lots, Lottes_Digits)의 결과는 엄격하게 0이어야 합니다. 드문 경우지만 마지막 숫자에 1의 차이가 있을 수 있지만(이유는 4번과 5번 지점에 있음) 결과 는 2.775557561562891e-17입니다. 이상합니다. 이러면 안 됩니다.
 

나는 부동 숫자의 내부를 뒤집는 약간의 튜토리얼 코드를 작성했습니다. 관심 있는 사람이 있으면 실행할 수 있습니다(C++ 코드, 온라인 컴파일러를 사용할 수 있습니다. 예를 들어 https://goo.gl/tP691X ).

 #include <iostream>
using namespace std;

int main()
{
    cout.precision( 17 );
     float f = 0.5 ;
     //float add = 0.00000002980232239; //-25   1/(2^25)
     float add = 0.00000005960464478 ; //-24     1/(2^24)
     //float add = 0.0000001192092896; //-23   1/(2^23)
     //float add = 0.0000002384185791; // -22  1/(2^22)
    f+= add;

    cout << "value = " << f << endl;
    cout << "----------\n" ;

     char *c = ( char *)&f;  // char может ссылаться на любой тип
    cout << "mantissa:\n" ;
    cout << "implicit_1 " ;
    cout << (c[ 2 ] >> 6 & 0 b1) << ' ' ; cout << (c[ 2 ] >> 5 & 0 b1) << ' ' ;
    cout << (c[ 2 ] >> 4 & 0 b1) << ' ' ; cout << (c[ 2 ] >> 3 & 0 b1) << ' ' ;
    cout << (c[ 2 ] >> 2 & 0 b1) << ' ' ; cout << (c[ 2 ] >> 1 & 0 b1) << ' ' ;
    cout << (c[ 2 ] >> 0 & 0 b1) << ' ' ; cout << (c[ 1 ] >> 7 & 0 b1) << ' ' ;
    cout << (c[ 1 ] >> 6 & 0 b1) << ' ' ; cout << (c[ 1 ] >> 5 & 0 b1) << ' ' ;
    cout << (c[ 1 ] >> 4 & 0 b1) << ' ' ; cout << (c[ 1 ] >> 3 & 0 b1) << ' ' ;
    cout << (c[ 1 ] >> 2 & 0 b1) << ' ' ; cout << (c[ 1 ] >> 1 & 0 b1) << ' ' ;
    cout << (c[ 1 ] >> 0 & 0 b1) << ' ' ; cout << (c[ 0 ] >> 7 & 0 b1) << ' ' ;
    cout << (c[ 0 ] >> 6 & 0 b1) << ' ' ; cout << (c[ 0 ] >> 5 & 0 b1) << ' ' ;
    cout << (c[ 0 ] >> 4 & 0 b1) << ' ' ; cout << (c[ 0 ] >> 3 & 0 b1) << ' ' ;
    cout << (c[ 0 ] >> 2 & 0 b1) << ' ' ; cout << (c[ 0 ] >> 1 & 0 b1) << ' ' ;
    cout << (c[ 0 ] >> 0 & 0 b1) << '\n' ;
    cout << "exponenta E - 127:\n" ;
    cout << "1= " << (c[ 2 ] >> 7 & 0 b1) << '\n' ;
    cout << "2= " << (c[ 3 ] >> 0 & 0 b1) << '\n' ;
    cout << "4= " << (c[ 3 ] >> 1 & 0 b1) << '\n' ;
    cout << "8= " << (c[ 3 ] >> 2 & 0 b1) << '\n' ;
    cout << "16= " << (c[ 3 ] >> 3 & 0 b1) << '\n' ;
    cout << "32= " << (c[ 3 ] >> 4 & 0 b1) << '\n' ;
    cout << "64= " << (c[ 3 ] >> 5 & 0 b1) << '\n' ;
    cout << "128= " << (c[ 3 ] >> 6 & 0 b1) << '\n' ;
    cout << "sign\n" ;
    cout << (c[ 3 ] >> 7 & 0 b00000001) << '\n' ;
}

f == 0.5 + 1/(2^24)에서 배기. 1/(2^24) - 주어진 차수에서 가수의 최하위 숫자:

value = 0.50000005960464478
----------
mantissa:
implicit_1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
exponenta E - 127 :
1 = 0
2 = 1
4 = 1
8 = 1
16 = 1
32 = 1
64 = 1
128 = 0
sign
0

도 = 126 - 127 = -1

가수 = 1.00000000000000000000001

사마귀를 거듭제곱으로 이동 -1 = 0.10000000000000000000001 = 1^(-1) + 1^(-24) = 1/(2^1) + 1/(2^7040) = 0.5 + 0.00000004578004


이론으로 https://habrahabr.ru/post/112953/ .

추신: 이 온라인 컴파일러는 http://rextester.com/l/cpp_online_compiler_gcc 에 더 적합할 것입니다.

 
pavlick_ :

나는 부동 숫자의 내부를 뒤집는 약간의 튜토리얼 코드를 작성했습니다. 관심 있는 사람이 있으면 실행할 수 있습니다(C++ 코드, 온라인 컴파일러를 사용할 수 있습니다. 여기 https://www.tutorialspoint.com/compile_cpp11_online.php ).

MQL5에서 실행할 수도 있습니다. 이 라이브러리 를 포함하여 c[Pos]를 _R(f)[(char)Pos](또는 _R(f).Bytes[Pos])로 바꾸십시오.

추신

 #include "fmtprntl.mqh"      // https://www.mql5.com/en/blogs/post/680570
#include <TypeToBytes.mqh> // https://www.mql5.com/ru/code/16280

#define c _R(f).Bytes
#define endl "\n"

void OnStart ()
{
  OutputStream cout( 16 , ' ' );
  
   float f = 0.5 ;
   //float add = 0.00000002980232239; //-25   1/(2^25)
   float add = 0.00000005960464478 ; //-24     1/(2^24)
   //float add = 0.0000001192092896; //-23   1/(2^23)
   //float add = 0.0000002384185791; // -22  1/(2^22)
  f+= add;

  cout << "value = " << f << endl;
  cout << "----------\n" ;

  cout << "mantissa:\n" ;
  cout << "implicit_1 " ;
  cout << (c[ 2 ] >> 6 & 1 ) << ' ' ; cout << (c[ 2 ] >> 5 & 1 ) << ' ' ;
  cout << (c[ 2 ] >> 4 & 1 ) << ' ' ; cout << (c[ 2 ] >> 3 & 1 ) << ' ' ;
  cout << (c[ 2 ] >> 2 & 1 ) << ' ' ; cout << (c[ 2 ] >> 1 & 1 ) << ' ' ;
  cout << (c[ 2 ] >> 0 & 1 ) << ' ' ; cout << (c[ 1 ] >> 7 & 1 ) << ' ' ;
  cout << (c[ 1 ] >> 6 & 1 ) << ' ' ; cout << (c[ 1 ] >> 5 & 1 ) << ' ' ;
  cout << (c[ 1 ] >> 4 & 1 ) << ' ' ; cout << (c[ 1 ] >> 3 & 1 ) << ' ' ;
  cout << (c[ 1 ] >> 2 & 1 ) << ' ' ; cout << (c[ 1 ] >> 1 & 1 ) << ' ' ;
  cout << (c[ 1 ] >> 0 & 1 ) << ' ' ; cout << (c[ 0 ] >> 7 & 1 ) << ' ' ;
  cout << (c[ 0 ] >> 6 & 1 ) << ' ' ; cout << (c[ 0 ] >> 5 & 1 ) << ' ' ;
  cout << (c[ 0 ] >> 4 & 1 ) << ' ' ; cout << (c[ 0 ] >> 3 & 1 ) << ' ' ;
  cout << (c[ 0 ] >> 2 & 1 ) << ' ' ; cout << (c[ 0 ] >> 1 & 1 ) << ' ' ;
  cout << (c[ 0 ] >> 0 & 1 ) << '\n' ;
  cout << "exponenta E - 127:\n" ;
  cout << "1= " << (c[ 2 ] >> 7 & 1 ) << '\n' ;
  cout << "2= " << (c[ 3 ] >> 0 & 1 ) << '\n' ;
  cout << "4= " << (c[ 3 ] >> 1 & 1 ) << '\n' ;
  cout << "8= " << (c[ 3 ] >> 2 & 1 ) << '\n' ;
  cout << "16= " << (c[ 3 ] >> 3 & 1 ) << '\n' ;
  cout << "32= " << (c[ 3 ] >> 4 & 1 ) << '\n' ;
  cout << "64= " << (c[ 3 ] >> 5 & 1 ) << '\n' ;
  cout << "128= " << (c[ 3 ] >> 6 & 1 ) << '\n' ;
  cout << "sign\n" ;
  cout << (c[ 3 ] >> 7 & 1 ) << '\n' ;
}

결과

 2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       0
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)      sign
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       128 =   0
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       64 =   1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       32 =   1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       16 =   1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       8 =   1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       4 =   1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       2 =   1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       1 =   0
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)      exponenta E - 127 :
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       implicit_1   0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 1
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       mantissa:
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)       ----------
2016.09 . 27 23 : 56 : 01.178 Test (Si- 12.16 ,H1)      value =   0.5000000596046448 
 
implicit_1   0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 0 32 1

가수에게 무슨 일이?

32는 문제의 ASCII 코드입니다. 오류 가 있는 라이브러리에 char 버전이 없는 것 같습니다. 가수의 값 사이의 공백을 제거해야 한다고 생각합니다. 아니면 ' ' 쓰기 " " 대신 ?

 
pavlick_ :

가수에게 무슨 일이?

32는 문제의 ASCII 코드입니다. 오류가 있는 라이브러리처럼 보입니다. 가수의 값 사이의 공백을 제거해야 한다고 생각합니다. 아니면 ' ' 쓰기 " " 대신 ?

fmtprntl.mqh는 내 것이 아니므로 확실히 말할 수 없습니다.

나는 귀찮게하고 싶지 않으므로 f를 위해 바이트 값을 인쇄했습니다.

 2016.09 . 28 00 : 34 : 09.813 Test (Si- 12.16 ,H1)      c[ 0 ] = 1
2016.09 . 28 00 : 34 : 09.813 Test (Si- 12.16 ,H1)      c[ 1 ] = 0
2016.09 . 28 00 : 34 : 09.813 Test (Si- 12.16 ,H1)      c[ 2 ] = 0
2016.09 . 28 00 : 34 : 09.813 Test (Si- 12.16 ,H1)      c[ 3 ] = 63
 
Slawa :

관련 부작용.

편리한 것으로 밝혀졌습니다. 그러나 이 용도는 원래 의도된 것이 아닙니다.

필요한 정확도로 실수를 인쇄하기 위한 특수 기능이 있습니다.

말해봐, 왜 계산 과정에서 실수를 반올림해야합니까? 실제로, 이 경우 계산의 정확성이 손실됩니다!

우리는 가격, 정류장, 제비의 정확한 비교에 대해 이야기하고 있습니다.

약간의 정밀도가 필요합니다