Double.Epsilon Pole
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Představuje nejmenší kladnou Double hodnotu, která je větší než nula. Toto pole je konstantní.
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
Hodnota pole
Value = 4.94065645841247E-324Poznámky
Hodnota vlastnosti odráží nejmenší kladnou Epsilon Double hodnotu, která je významná v numerických operacích nebo porovnávání, když je hodnota Double instance nula. Například následující kód ukazuje, že nula a Epsilon jsou považovány za nerovné hodnoty, zatímco nula a polovina hodnoty Epsilon jsou považovány za rovno.
using System;
public class Example
{
public static void Main()
{
double[] values = { 0, Double.Epsilon, Double.Epsilon * .5 };
for (int ctr = 0; ctr <= values.Length - 2; ctr++)
{
for (int ctr2 = ctr + 1; ctr2 <= values.Length - 1; ctr2++)
{
Console.WriteLine("{0:r} = {1:r}: {2}",
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 $"{values[i]:r} = {values[i2]:r}: {values[i].Equals values[i2]}"
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("{0:r} = {1:r}: {2}", _
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
Přesněji řečeno, formát s plovoucí desetinnou čárkou se skládá ze znaménka, 52bitové mantissa nebo significandu a 11bitové exponentu. Jak ukazuje následující příklad, nula má exponent -1022 a mantissa 0. Epsilon má exponent -1022 a mantissa 1. To znamená, že Epsilon je nejmenší kladná Double hodnota větší než nula a představuje nejmenší možnou hodnotu a nejmenší možný přírůstek pro Double exponent je -1022.
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("{0:R}: ", 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: {0}\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;
exponent = exponent | ((bytes[6] & 0xF0) >> 4);
int adjustment = exponent != 0 ? 1023 : 1022;
result += String.Format("{0}Exponent: 0x{1:X4} ({1})\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("{0}Mantissa: 0x{1:X13}\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 = $"{value:R}: "
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: {if (bytes[7] &&& 0x80uy) = 0x80uy then "1 (-)" else "0 (+)"}\n"""
// Get the exponent (byte 6 bits 4-7 to byte 7, bits 0-6)
let exponent = (bytes[7] &&& 0x07Fuy) <<< 4
let exponent = exponent ||| ((bytes[6] &&& 0xF0uy) >>> 4)
let adjustment = if exponent <> 0uy then 1022 else 1023
let result = result + $"{String(' ', indent)}Exponent: 0x{int exponent - adjustment:X4} ({int exponent - adjustment})\n"
// Get the significand (bits 0-51)
let significand = (bytes[6] &&& 0x0Fuy) <<< 48
let significand = significand ||| byte (int64 bytes[5] <<< 40)
let significand = significand ||| byte (int64 bytes[4] <<< 32)
let significand = significand ||| byte (int64 bytes[3] <<< 24)
let significand = significand ||| byte (int64 bytes[2] <<< 16)
let significand = significand ||| byte (int64 bytes[1] <<< 8)
let significand = significand ||| bytes[0]
result + $"{String(' ', indent)}Mantissa: 0x{significand:X13}\n"
let values = [| 0.; Double.Epsilon |]
for value in values do
printfn $"{getComponentParts value}"
printfn ""
// // The example displays the following output:
// 0: Sign: 0 (+)
// Exponent: 0xFFFFFC02 (-1022)
// Mantissa: 0x0000000000000
//
//
// 4.94065645841247E-324: Sign: 0 (+)
// Exponent: 0xFFFFFC02 (-1022)
// Mantissa: 0x0000000000001
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("{0:R}: ", 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: {0}{1}",
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
exponent = exponent Or ((bytes(6) And &HF0) >> 4)
Dim adjustment As Integer = If(exponent <> 0, 1023, 1022)
result += String.Format("{0}Exponent: 0x{1:X4} ({1}){2}",
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("{0}Mantissa: 0x{1:X13}{2}",
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
Epsilon Vlastnost však není obecnou mírou přesnosti Double typu; vztahuje se pouze na Double instance, které mají hodnotu nula nebo exponent -1022.
Poznámka
Hodnota Epsilon vlastnosti není ekvivalentní stroj epsilon, který představuje horní mez relativní chyby kvůli zaokrouhlení v aritmetice s plovoucí desetinou čárkou.
Hodnota této konstanty je 4,94065645841247e-324.
Dvě zdánlivě ekvivalentní čísla s plovoucí desetinou čárkou nemusí porovnávat stejné, protože rozdíly v jejich nejmenších významných číslicích. Výraz jazyka C# například nerovná se, (double)1/3 == (double)0.33333
protože operace dělení na levé straně má maximální přesnost, zatímco konstanta na pravé straně je přesná pouze na zadané číslice. Pokud vytvoříte vlastní algoritmus, který určuje, jestli se dvě čísla s plovoucí desetinou čárkou dají považovat za rovna, nedoporučujeme, abyste svůj algoritmus založil na hodnotě Epsilon konstanty, abyste vytvořili přijatelný absolutní okraj rozdílu pro dvě hodnoty, které se mají považovat za stejné. (Obvykle je tento okraj rozdílu mnohokrát větší než Epsilon.) Informace o porovnávání dvou dvou hodnot s plovoucí desetinou čárkou naleznete Double a Equals(Double).
Poznámky k platformě
V systémech ARM je hodnota Epsilon konstanty příliš malá, aby byla zjištěna, takže odpovídá nule. Můžete definovat alternativní hodnotu epsilon, která se rovná 2,2250738585072014E-308.