가격 수 != 가격 ?

 

앞으로 더 나은 코드를 작성할 수 있도록 이상한 점을 이해하려고 노력하고 있습니다. . .

내 표시기 중 하나에서 이상한 일이 발생하는 것을 알아차리고 제대로 작동하지 않아 코드를 확인했는데 올바른 것 같습니다. 그래서 나는 약간의 조사를 했고 결국 약간의 테스트 Indicator 를 만들었습니다.

본질적으로 이것은 사실인 것 같습니다. . .

 double TestValue = iClose ( NULL , 0 , 0 );
   
if (TestValue != NormalizeDouble (TestValue, Digits ) )

. . . 어떻게 이런 일이 일어나는지 아세요?

 
이전에 질문 하고 답변한 내용
 
RaptorUK :

. . . 어떻게 이런 일이 일어나는지 아세요?

NormalizeDouble()의 내부 작동에 달려 있습니다. 예를 들어...

   double TestValue = 1.57373 ;
   if (TestValue != NormalizeDouble (TestValue, 5 )) MessageBox ( "WTF?" );

우연히 다음을 수행하면 동일한 결과가 나타납니다.

   double TestValue = StrToDouble ( "1.57373" );
   if (TestValue != NormalizeDouble (TestValue, 5 )) MessageBox ( "WTF?" );

초기 할당 후 TestValue = 1.573730000000000 1 . NormalizeDouble(..., 5)은 1.5737299999999999를 생성합니다.

 
WHRoeder :
이전에 묻고 답변한 내용
존경하는 마음으로, 그 게시물이 이 스레드에서 내 문제에 대한 답변을 제공하지 않는다고 생각합니다.
NormalizeDouble 이외의 다른 방법이 있다는 것을 알고 있습니다. . . 내가 이해하지 못하는 것은 iClose가 아직 Normalized되지 않은 값을 반환하는 이유입니다. .
 
jjc :

NormalizeDouble()의 내부 작동에 달려 있습니다. 예를 들어...

부수적으로 다음을 수행하면 동일한 결과가 나타납니다.

초기 할당 후 TestValue = 1.573730000000000 1 . NormalizeDouble(..., 5)은 1.5737299999999999를 생성합니다.


그렇다면 TestValue가 > 또는 <가 아닌 1.57373과 같게 하려면 어떻게 해야 합니까?
 
RaptorUK :

그렇다면 TestValue가 > 또는 <가 아닌 1.57373과 같게 하려면 어떻게 해야 합니까?
이것이 아직 명확하지 않은 경우 1.57373은 부동 소수점 값 으로 정확하게 표현할 수 없습니다. 0.1과 같은 값도 마찬가지입니다. 유일한 이상한 점은 NormalizeDouble()이 MQ4 언어의 다른 부분에 대해 다른 근사값을 사용한다는 것입니다.
 
jjc :
이것이 아직 명확하지 않은 경우 1.57373은 부동 소수점 값으로 정확하게 표현할 수 없습니다. 0.1과 같은 값도 마찬가지입니다. 유일한 이상한 점은 NormalizeDouble()이 MQ4 언어의 다른 부분에 대해 다른 근사값을 사용한다는 것입니다.

아 . . 아니 명확하지 않았습니다. . 나는 그것을 몰랐다. 감사합니다. 조사하겠습니다.
 
RaptorUK :
아 . . 아니 명확하지 않았습니다. . 나는 그것을 몰랐다. 감사합니다. 조사하겠습니다.

부동 소수점 값과 산술은 컴퓨터 프로세서에 바로 내장되어 있기 때문에 빠르지만 일부 값은 부동 소수점 변수로 정확하게 표현할 수 없다는 단점이 있습니다. (속도 관련 예는 https://www.mql5.com/en/forum/116228/page2#156859 참조 ).

사실상, 복식과 관련된 모든 것은 일종의 반올림 오류를 유발할 수 있습니다. 이것은 모든 종류의 재미있는 단점으로 이어집니다. 예를 들어 0.1 * 10 = 1.0이지만 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 != 1.0입니다.

그 결과 NormalizeDouble(x, y)이 Round(x, y)와 정확히 동의어가 아닙니다. NormalizeDouble()은 반올림된 값에 가장 가까운 부동 소수점 근사값을 반환합니다. NormalizeDouble(a, n) == NormalizeDouble(b, n)을 수행하면 기본적으로 "a와 b가 동일하므로 부동 소수점 산술이 소수점 이하 자릿수 n개 이상에서 반올림 차이가 발생할 수 있다는 사실을 허용합니까?"라고 말하는 것입니다.

많은 사람들이 말했듯이 NormalizeDouble(a, 5) == NormalizeDouble(b, 5) 는 사실상 MathAbs(a - b) < 0.00001과 동일하며 후자는 약간 더 빠르게 실행됩니다. 후자는 NormalizeDouble() 함수에 상응하는 편리한 기능을 제공하지 않는 언어/플랫폼에서 널리 사용되기 때문에 일반적입니다. 그러나 성능 차이가 너무 작아서 코드를 더 읽기 쉽게 만든다고 생각되면 NormalizeDouble()을 사용하겠습니다.

이 모든 것은 이중 데이터 유형이 있는 언어의 경우 완벽하게 정상입니다. 일부 독점적이고 일반적인 MQ4 기이함을 도입하는 비트는 1.57373 != NormalizeDouble(1.57373, 5)입니다. 상수 1.57373을 선언하는 것과 NormalizeDouble()을 사용하는 것이 서로 다른 최상의 경우 부동 소수점 값을 선택하는 것은 잘못된 것입니다.

 

고맙습니다. :-)

나는 그 문제를 알고 있었지만 그 이유를 잘 알지 못했고 따라서 가능한 의미를 완전히 인식하지 못했습니다.

 
0을 제외하고는 절대 두 배를 비교하지 않음
 if (a > b)
 if (a - b > Point / 2 .)
 if (a >= b)
 if (a - b > - Point )
 if (a != b)
 if ( MathAbs (a - b) > Point / 2 .)
 
WHRoeder :
0을 제외하고는 절대 두 배를 비교하지 않음


정확히 100줄이 넘는 코드가 있습니다. . . 그리고 눈에 보이는 거의 모든 것에 NormalizeDouble을 사용 하여 안정적으로 작동하도록 했습니다. 나는 당신의 제안 뒤에 있는 아이디어를 이해합니다. 감사합니다. 하지만 그것들이 내 코드의 가독성에 부정적인 영향을 미치고 따라서 미래에 수정의 용이성에 부정적인 영향을 미칠 수 있다고 생각합니다.

머지않은 장래에 이 코드 블록을 수정하여 차트가 실행 중인 차트의 시간대가 아닌 다른 시간대에서 작동하도록 할 것입니다. 이 작업을 수행할 때 NormalizeDoubles를 근절하고 다른 것으로 교체할 계획입니다. . . 아직 100% 확실하지 않으며 비교 전에 정수로 변환할 수 있습니다. .

평소와 같이 도움을 주셔서 감사합니다 :-)