在MT4中通过NormalizeDouble对数字进行四舍五入 - 页 16

 
fxsaber:
废弃的

标准库有 一个颗粒度感知的价格归一化功能

//+------------------------------------------------------------------+
//| 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:

标准库有 一个颗粒度感知的价格归一化功能

我知道这种极其缓慢的实施。这是对NormalizeDouble(和Help)的微调,以适应当前的现实。每个人都可以写自己的颗粒度。
 
transcendreamer:
我开始猜测NormalizeDouble(new_lot-sum_lots,Lots_Digits);它并不完全输出0,而是存储一些尾数

如果变量new_lot和sum_lots相等,那么差值正好为0。但不知道你是如何计算的,它们在计算时可能确实不相等,因此有非零的差异。像这样做同样的事情。

NormalizeDouble(new_lot, Lots_Digits) - NormalizeDouble(sum_lots, Lots_Digits)。

如果变量在指定位数内相等,那么差值将严格为0。

 
Sergei Vladimirov:

如果变量new_lot和sum_lots相等,那么差值正好为0。但不知道你是如何计算的,它们在计算时可能确实不相等,因此有非零的差异。像这样做同样的事情。

NormalizeDouble(new_lot, Lots_Digits) - NormalizeDouble(sum_lots, Lots_Digits)。

如果变量在指定的位数内相等,差值将严格为0。

哦,谢谢你!
 
transcendreamer:

再次关于四舍五入......

请告知有关情况(不要扔西红柿,我是一个人道主义者)。

有这样一个变量。

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

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

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

德尔塔最初是规范化的。

OrderLots可能应该返回规范化的配音。

但不知何故,有时在罕见的情况下,我得到了2.775557561562891e-17这样的数字。

所以它几乎是零,但不是零.......

第一个问题 - 这是否正常?

...


我又仔细读了一遍。这是不正常的。如果NormalizeDouble函数 操作

  1. 整数部分被选中 - I
  2. 分数部分被选中 - F
  3. F = F * 10^digits
  4. F = F(+或-取决于符号) 0.5
  5. F = (F的整数部分) / 10^个数字
  6. 结果 = I + F
那么如果new_lot和sum_lots在指定的位数内相等,NormalizeDouble(new_lot - sum_lots, Lots_Digits) 的结果也应严格为零在极少数情况下,最后一位数字可能相差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.000000000000000000001

将尾数移至-1度=0.100000000000000001=1^(-1)+1^(-24)=1/(2^1)+1/(2^24)=0.5+0.00000005960464478=0.50000005960464478


作为一个理论https://habrahabr.ru/post/112953/。

SZZ:这个在线编译器比http://rextester.com/l/cpp_online_compiler_gcc

 
pavlick_:

我写了一个小的教程代码(我自己也有兴趣去探究),把一个浮动数的内脏翻出来。如果有人感兴趣,你可以运行它(C++代码,你可以使用一些在线编译器。这里https://www.tutorialspoint.com/compile_cpp11_online.php, 例如)

你也可以在MQL5中运行它--通过连接这个库,用_R(f)[(char)Pos](或_R(f).Bytes[Pos])代替c[Pos]。

SZ

#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:

一个相关的副作用。

事实证明这很方便。但它最初并不打算以这种方式使用。

有一些特殊的功能用于打印具有所需精度的实数。

告诉我为什么在计算过程中需要对实数进行四舍五入?因为在这种情况下,你会失去计算的准确性!

我们谈论的是价格的正确比较,停止,地段

你在这里需要有一定的准确性。