> В компьютере точность хранения количества десятичных знаков числа определяется размерами мантиссы и ограничена 52 битами.
Ни как нет. На самом деле процессор поддерживает машинные операции с числами типа extended (собственно говоря это родной тип данных математического сопроцессора).
У него "19 significant digits, exponent -4932 to +4932" - это 80битное число, в отличии от 64битного типа double, о котором Вы пишите.
Ирония ситуации состоит в том, что С, на котором написан МТ, просто напросто не поддерживает этот тип данных.
Соответственно и МТ его не поддерживает - а очень жаль, это наиболее точное число из доступных для нативной обработки процессором.
PS. но в целом, статья нужная, да.
Позанудствую.
double MathModCorrect(double a, double b, int precisionRatio = -5) { double correction = MathMin(MathAbs(a), MathAbs(b))*MathPow(10, precisionRatio); if (a > 0) a += correction; else a -= correction; int tmpres = a/b; return (a - tmpres*b); }А вообще штука нужная. Чуть бы поменьше сумбура и побольше четкости в изложении, было бы совсем хорошо.
> В компьютере точность хранения количества десятичных знаков числа определяется размерами мантиссы и ограничена 52 битами.
Ни как нет. На самом деле процессор поддерживает машинные операции с числами типа extended (собственно говоря это родной тип данных математического сопроцессора). У него "19 significant digits, exponent -4932 to +4932" - это 80битное число, в отличии от 64битного типа double, о котором Вы пишите.
Спасибо. Скорректировал.
Вы правы, с extended (например, на Delphi) мы бы получили результат -4951 вместо -324 с double.
Позанудствую.
double MathModCorrect(double a, double b, int precisionRatio = -5) { double correction = MathMin(MathAbs(a), MathAbs(b))*MathPow(10, precisionRatio); if (a > 0) a += correction; else a -= correction; int tmpres = a/b; return (a - tmpres*b); }А вообще штука нужная. Чуть бы поменьше сумбура и побольше четкости в изложении, было бы совсем хорошо.
Спасибо. А сумбур получился из-за того, что это заметка типа коллажа различных вопросов.
Насчет добавления погрешности, пусть даже небольшой, то я бы не советовал.
Вот например,
#include <stdlib.mqh> double MathModCorrect1(double a, double b) { int tmpres = a/b; return (a - tmpres*b); } double MathModCorrect2(double a, double b, int precisionRatio = -5) { double correction = MathMin(MathAbs(a), MathAbs(b))*MathPow(10, precisionRatio); if (a > 0) a += correction; else a -= correction; int tmpres = a/b; return (a - tmpres*b); } int start() { double c1,c2; c1=MathModCorrect1(5.3,2.0); c2=MathModCorrect2(5.3,2.0); Alert("MathMod1(5.3,2.0): Output:",c1,", 8 digits precision:"+DoubleToStr(c1,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c1,15)); Alert("MathMod2(5.3,2.0): Output:",c2,", 8 digits precision:"+DoubleToStr(c2,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c2,15)); c1=MathModCorrect1(18.5,4.2); c2=MathModCorrect2(18.5,4.2); Alert("MathMod1(18.5,4.2): Output:",c1,", 8 digits precision:"+DoubleToStr(c1,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c1,15)); Alert("MathMod2(18.5,4.2): Output:",c2,", 8 digits precision:"+DoubleToStr(c2,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c2,15)); c1=MathModCorrect1(14.5,3.5); c2=MathModCorrect2(14.5,3.5); Alert("MathMod1(14.5,3.5): Output:",c1,", 8 digits precision:"+DoubleToStr(c1,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c1,15)); Alert("MathMod2(14.5,3.5): Output:",c2,", 8 digits precision:"+DoubleToStr(c2,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c2,15)); // один из случаев с ошибкой в стандартной MathMod c1=MathModCorrect1(5.0,0.1); c2=MathModCorrect2(5.0,0.1); Alert("MathMod1(5.0,0.1): Output:",c1,", 8 digits precision:"+DoubleToStr(c1,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c1,15)); Alert("MathMod2(5.0,0.1): Output:",c2,", 8 digits precision:"+DoubleToStr(c2,8)+ ", 15 digits precision:"+ DoubleToStrMorePrecision(c2,15)); return(0); }
Выведет:
MathMod1(5.3,2.0): Output:1.3, 8 digits precision:1.30000000, 15 digits precision:1.300000000000000
MathMod2(5.3,2.0): Output:1.3, 8 digits precision:1.30002000, 15 digits precision:1.300020000000000
MathMod1(18.5,4.2): Output:1.7, 8 digits precision:1.70000000, 15 digits precision:1.699999999999999
MathMod2(18.5,4.2): Output:1.7, 8 digits precision:1.70004200, 15 digits precision:1.700042000000000
MathMod1(14.5,3.5): Output:0.5, 8 digits precision:0.50000000, 15 digits precision:0.500000000000000
MathMod2(14.5,3.5): Output:0.5, 8 digits precision:0.50003500, 15 digits precision:0.500035000000000
MathMod1(5.0,0.1): Output:0, 8 digits precision:0.00000000, 15 digits precision:0.000000000000000
MathMod2(5.0,0.1): Output:0, 8 digits precision:0.00000100, 15 digits precision:0.000001000000000
Диапазон возможных значений чисел double гораздо шире: -1.7*e-308 до 1.7*e308
PS. но в целом, статья нужная, да.
Да, статья жизненная :) Хотя все это давно известно, но вспомнить и увидеть практически было очень интересно.
Диапазон возможных значений чисел double гораздо шире: -1.7*e-308 до 1.7*e308
Вообще говоря, диапазон вот такой должен быть:
наименование формата | single-precision | double-precision |
длина числа, бит | 32 | 64 |
смещенная экспонента (E), бит | 8 | 11 |
остаток от мантиссы (M), бит | 23 | 52 |
смещение | 127 | 1023 |
формула расчета денормализованных чисел | F =(-1)S∙2(E -126)∙ M/223 | F =(-1)S∙2(E -1022)∙M/252 |
формула расчета нормализованных чисел | F =(-1)S∙2(E-127)∙(1+ M/223) | F =(-1)S∙2(E-1023)∙(1+M/252) |
минимальное число | ±2-149≈ ±1,40129846∙e-45 | ±2-1074≈ ± 4,94065646∙e-324 |
максимальное число | ±2127∙(2-2-23) ≈ ± 3,40282347∙e+38 | ±21023∙(2-2-52) ≈ ± 1,79769313∙e+308 |
У разработчиков ошибка в описании. Они его наверное взяли из описания С, так же как и все это делают. Но реальность другая.
Так что лично мне больше нравится первый вариант :)
Блин. Тоже молодец, поленился протестировать.
double MathModCorrect(double a, double b, int precisionRatio = -5) { double a_ = a; double correction = MathMin(MathAbs(a), MathAbs(b))*MathPow(10, precisionRatio); if (a_ > 0) a_ += correction; else a_ -= correction; int tmpres = a_/b; return (a - tmpres*b); }
![MQL5 - Язык торговых стратегий для клиентского терминала MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
New article Особенности работы с числами типа double в MQL4 has been published:
Author: MetaQuotes Software Corp.