Машинное эпсилон
Машинный ноль (англ. computer zero ) — представление нуля в вычислительной системе. Машинным нулём обозначаются числа, абсолютная величина которых меньше наименьшей ненулевой величины из диапазона изменения чисел данной вычислительной системы. [1]
Проблема машинного нуля в том, что два числа считаются одинаковыми, если они отличаются на величину, меньшую по модулю, чем машинный ноль.
При представлении чисел со знаком в обратных двоичных кодах существуют проблема наличия двух обратных кодов числа 0: «положительный нуль» и «отрицательный нуль».
См. также
Wikimedia Foundation . 2010 . Экспорт словарей на сайты, сделанные на PHP, Действия с плавающими числами из-за ошибок округления лишь приближенно отражают арифметику настоящих вещественных чисел. Так, если к большому плавающему числу прибавить очень маленькое, то оно не изменится. Действительно, при выравнивании порядков все значащие биты мантиссы меньшего числа могут выйти за пределы разрядной сетки, в результате чего оно станет равным нулю. Таким образом, с плавающими числами возможна ситуация, когда a+b = a при b 0 Более того, для сложения не выполняется закон ассоциативности: Действительно, пусть ε — максимальное плавающее число среди чисел, удовлетворяющих условию (приведенные выше рассуждения показывают, что такие числа существуют). Тогда поскольку левая часть неравенства равна единице, а правая строго больше единицы (это следует из максимальности числа ε). Число ε часто называют машинным эпсилоном или, чуть менее корректно, машинным нулем, поскольку при прибавлении к единице оно ведет себя как ноль. Величина машинного эпсилона характеризует точность операций компьютера. Она примерно одинакова для всех современных компьютеров: большинство процессоров работают с восьмибайтовыми плавающими числами (тип double в Си), а арифметика плавающих чисел подчиняется строгим международным стандартам. Оценим величину машинного эпсилона для типа double. Число 1.0 записывается в плавающей форме как Порядок плавающего числа 1.0 равен нулю. При сложении 1.0 с числом ε производится выравнивание порядка путем многократного сдвига мантиссы числа ε вправо и увеличения его порядка на 1. Поскольку все разряды числа ε должны в результате выйти за пределы разрядной сетки, должно быть выполнено 53 сдвига. Порядок числа ε после этого должен стать равным порядку числа 1.0, т.е. нулю. Следовательно, изначально порядок числа ε должен быть равным -53: где m — число в диапазоне от единицы до двух. Таким образом, величина машинного эпсилона составляет примерно 2 -53 10 -16 Приблизительно точность вычислений составляет 16 десятичных цифр. (Это также можно оценить следующим образом: 53 двоичных разряда составляют примерно 15.95 десятичных, поскольку 53/log210 53/3.321928 15.95.) В случае четырехбайтовых плавающих чисел (тип float языка Си) точность вычислений составляет примерно 7 десятичных цифр. Это очень мало, поэтому тип float чрезвычайно редко применяется на практике. К тому же процессор сконструирован для работы с восьмибайтовыми вещественными числами, а при работе с четырехбайтовыми он все равно сначала приводит их к восьмибайтовому типу. В программировании следует избегать типа float и всегда пользоваться типом double. Некоторые процессоры применяют внутреннее представление плавающих чисел с большим количеством разрядов мантиссы. Например, процессор Intel использует 80-битовое (десятибайтовое) представление. Поэтому точность вычислений, которые не записывают промежуточные результаты в память, может быть несколько выше указанных оценок. Кроме потери точности, при операциях с вещественными числами могут происходить и другие неприятности: Кроме того, некорректной операцией является деление на ноль. В отличие от операций с целыми числами, переполнение и исчезновение порядка считаются ошибочными ситуациями и приводят к аппаратному прерыванию работы процессора. Программист может задать реакцию на прерывание — либо аварийное завершение программы, либо, например, при переполнении присваивать результату специальное значение плюс или минус бесконечность, а при исчезновении порядка — ноль. Заметим, что среди двоичных кодов, представляющих плавающие числа, имеется несколько специальных значений. Перечислим некоторые из них: Любые операции с константой NaN приводят к прерыванию, поэтому она удобна при отладке программы — ею перед началом работы программы инициализируются значения всех вещественных переменных. Если в результате ошибки программиста при вычислении выражения используется переменная, которой не было присвоено никакого значения, то происходит прерывание из-за операции со значением NaN и ошибка быстро отслеживается. К сожалению, в случае целых чисел такой константы нет: любой двоичный код представляет некоторое целое число. Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений. Представляет наименьшее положительное значение Double больше нуля. Это поле является константой. Value = 4.94065645841247E-324 Значение свойства отражает наименьшее Epsilon положительное Double значение, которое имеет значение в числовых операциях или сравнениях, когда значение экземпляра Double равно нулю. Например, следующий код показывает, что ноль и Epsilon считаются неравными значениями, тогда как ноль и половина значения Epsilon считаются равными. Точнее, формат с плавающей запятой состоит из знака, 52-битовой мантиссы или знака и 11-битовой экспоненты. Как показано в следующем примере, ноль имеет экспоненту -1022 и мантиссу 0. Epsilon имеет экспоненту -1022 и мантиссу 1. Это означает, что Epsilon является наименьшим положительным Double значением больше нуля и представляет наименьшее возможное значение и наименьший возможный приращение для объекта Double с экспонентой -1022. Epsilon Однако свойство не является общей мерой точности Double типа; оно применяется только к Double экземплярам со значением 0 или экспонентой -1022. Значение Epsilon свойства не эквивалентно значению machine epsilon, представляющего верхнюю границу относительной ошибки из-за округления в арифметическом режиме с плавающей запятой. Значение этой константы равно 4,94065645841247e-324. Два явно эквивалентных числа с плавающей запятой могут не сравниваться равными из-за различий в их наименее значимых цифрах. Например, выражение C# не сравнивается равным, так как операция деления слева имеет максимальную точность, (double)1/3 == (double)0.33333 а константы справа — только указанные цифры. При создании пользовательского алгоритма, который определяет, можно ли считать два числа с плавающей запятой равными, не рекомендуется основывать алгоритм на значении Epsilon константы, чтобы установить приемлемый абсолютный предел разницы для двух значений, которые будут считаться равными. (Как правило, эта разница во много раз больше, чем Epsilon.) Сведения о сравнении двух значений двойной точности с плавающей запятой см. в разделах Double и Equals(Double). В системах ARM значение Epsilon константы слишком мало для обнаружения, поэтому оно равно нулю. Вместо этого можно определить альтернативное значение epsilon, равное 2,2250738585072014E-308. В питоне есть sys.float_info.epsilon и эта величина является машинным эпсилоном. Это я понял. Так же я понял, что существуют значения меньше машинного эпсилона, но с этими значениями компьютер работает не точно. В последней строчке, нижеследующего кода, я делю машинный эпсилон на 2 и получаю значение меньше машинного эпсилона, потом я это значение складываю с единицей и в результате получаю число чуть больше единицы, но это "чуть", меньше числа, которое компьютер может представить корректно и поэтому компьютер это "чуть" округляет до нуля и в итоге, в последней строчке, я получаю единицу без изменений. Итого у меня два вопроса: 2) Машинный эпсилон и машинный ноль это синонимы?Ссылки
Полезное
Смотреть что такое «Машинное эпсилон» в других словарях:
WordPress, MODx.
Машинный эпсилон
Double. Epsilon Поле
public: double Epsilon = 4.94065645841247E-324;
public const double Epsilon = 4.94065645841247E-324;
val mutable Epsilon : double
Public Const Epsilon As Double = 4.94065645841247E-324
Значение поля
Комментарии
using System; public class Example < public static void Main() < double[] values = < 0, Double.Epsilon, Double.Epsilon * .5 >; for (int ctr = 0; ctr = : ", values[ctr], values[ctr2], values[ctr].Equals(values[ctr2])); > Console.WriteLine(); > > > // The example displays the following output: // 0 = 4.94065645841247E-324: False // 0 = 0: True // // 4.94065645841247E-324 = 0: False
open System let values = [| 0.; Double.Epsilon; Double.Epsilon * 0.5 |] for i = 0 to values.Length - 2 do for i2 = i + 1 to values.Length - 1 do printfn $" = : " printfn "" // The example displays the following output: // 0 = 4.94065645841247E-324: False // 0 = 0: True // // 4.94065645841247E-324 = 0: False
Module Example Public Sub Main() Dim values() As Double = < 0, Double.Epsilon, Double.Epsilon * .5 >For ctr As Integer = 0 To values.Length - 2 For ctr2 As Integer = ctr + 1 To values.Length - 1 Console.WriteLine(" = : ", _ values(ctr), values(ctr2), _ values(ctr).Equals(values(ctr2))) Next Console.WriteLine() Next End Sub End Module ' The example displays the following output: ' 0 = 4.94065645841247E-324: False ' 0 = 0: True ' ' 4.94065645841247E-324 = 0: False
using System; public class Example < public static void Main() < double[] values = < 0.0, Double.Epsilon >; foreach (var value in values) < Console.WriteLine(GetComponentParts(value)); Console.WriteLine(); >> private static string GetComponentParts(double value) < string result = String.Format(": ", value); int indent = result.Length; // Convert the double to an 8-byte array. byte[] bytes = BitConverter.GetBytes(value); // Get the sign bit (byte 7, bit 7). result += String.Format("Sign: \n", (bytes[7] & 0x80) == 0x80 ? "1 (-)" : "0 (+)"); // Get the exponent (byte 6 bits 4-7 to byte 7, bits 0-6) int exponent = (bytes[7] & 0x07F) > 4); int adjustment = exponent != 0 ? 1023 : 1022; result += String.Format("Exponent: 0x ()\n", new String(' ', indent), exponent - adjustment); // Get the significand (bits 0-51) long significand = ((bytes[6] & 0x0F) << 48); significand = significand | ((long) bytes[5] << 40); significand = significand | ((long) bytes[4] << 32); significand = significand | ((long) bytes[3] << 24); significand = significand | ((long) bytes[2] << 16); significand = significand | ((long) bytes[1] << 8); significand = significand | bytes[0]; result += String.Format("Mantissa: 0x\n", new String(' ', indent), significand); return result; > > // // The example displays the following output: // 0: Sign: 0 (+) // Exponent: 0xFFFFFC02 (-1022) // Mantissa: 0x0000000000000 // // // 4.94065645841247E-324: Sign: 0 (+) // Exponent: 0xFFFFFC02 (-1022) // Mantissa: 0x0000000000001
open System let getComponentParts (value: double) = let result = $": " let indent = result.Length // Convert the double to an 8-byte array. let bytes = BitConverter.GetBytes value // Get the sign bit (byte 7, bit 7). let result = result + $"""Sign: \n""" // Get the exponent (byte 6 bits 4-7 to byte 7, bits 0-6) let exponent = (bytes[7] &&& 0x07Fuy) >> 4) let adjustment = if exponent <> 0uy then 1022 else 1023 let result = result + $"
Module Example Public Sub Main() Dim values() As Double = < 0.0, Double.Epsilon >For Each value In values Console.WriteLine(GetComponentParts(value)) Console.WriteLine() Next End Sub Private Function GetComponentParts(value As Double) As String Dim result As String = String.Format(": ", value) Dim indent As Integer = result.Length ' Convert the double to an 8-byte array. Dim bytes() As Byte = BitConverter.GetBytes(value) ' Get the sign bit (byte 7, bit 7). result += String.Format("Sign: ", If((bytes(7) And &H80) = &H80, "1 (-)", "0 (+)"), vbCrLf) ' Get the exponent (byte 6 bits 4-7 to byte 7, bits 0-6) Dim exponent As Integer = (bytes(7) And &H07F) > 4) Dim adjustment As Integer = If(exponent <> 0, 1023, 1022) result += String.Format("Exponent: 0x ()", New String(" "c, indent), exponent - adjustment, vbCrLf) ' Get the significand (bits 0-51) Dim significand As Long = ((bytes(6) And &H0F) << 48) significand = significand Or (bytes(5) << 40) significand = significand Or (bytes(4) << 32) significand = significand Or (bytes(3) << 24) significand = significand Or (bytes(2) << 16) significand = significand Or (bytes(1) << 8) significand = significand Or bytes(0) result += String.Format("Mantissa: 0x", New String(" "c, indent), significand, vbCrLf) Return result End Function End Module ' The example displays the following output: ' 0: Sign: 0 (+) ' Exponent: 0xFFFFFC02 (-1022) ' Mantissa: 0x0000000000000 ' ' ' 4.94065645841247E-324: Sign: 0 (+) ' Exponent: 0xFFFFFC02 (-1022) ' Mantissa: 0x0000000000001
Заметки о платформе
Что такое машинный эпсилон?
x = sys.float_info.epsilon ''' this is how to work machine epsilon 1.0 + x != 1.0 1.0 + x/2 == 1.0 ''' print (1.0 + x) # output will be 1.0000000000000002 print (1.0 + x/2) # output will be 1.0
1) Правильно ли я понимаю, что машинный эпсилон это минимальная разница между двумя числами, с которой компьютер может работать без погрешностей?