Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
Hodnota vlastnosti Epsilon odráží nejmenší kladnou Double hodnotu, která je významná v numerických operacích nebo porovnání, pokud je hodnota Double instance nula. Následující kód například ukazuje, že nula a Epsilon jsou považovány za nerovné hodnoty, zatímco nula a polovina hodnoty Epsilon se považují za rovnou.
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($"{values[ctr]:r} = {values[ctr2]:r}: {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é mantisy a 11bitového exponentu. Jak ukazuje následující příklad, nula má exponent -1022 a mantisu 0. Epsilon má exponent -1022 a mantisu 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 hodnotu, jejíž exponent je -1022.
using System;
public class Example1
{
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 Example1
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 vlastnosti Epsilon není ekvivalentní strojovému epsilonu, který představuje horní mez relativní chyby způsobené zaokrouhlením v aritmetice s pohyblivou řádovou čárkou.
Hodnota této konstanty je 4,94065645841247e-324.
Dvě zdánlivě ekvivalentní čísla s plovoucí desetinou čárkou nemusí být považována za stejná kvůli rozdílům v jejich nejméně významných číslicích. Například výraz C# (double)1/3 == (double)0.33333
se nerovná, protože operace dělení na levé straně má maximální přesnost, zatímco konstanta na pravé straně je přesná pouze na specifikované číslice. Pokud vytvoříte vlastní algoritmus, který určuje, zda lze považovat dvě čísla s plovoucí desetinou čárkou za stejná, nedoporučujeme, abyste svůj algoritmus založil na hodnotě Epsilon konstanty pro stanovení přijatelné absolutní odchylky, kterou mohou mít dvě hodnoty, aby se považovaly za stejné. (Tento rozdíl je obvykle mnohokrát větší než Epsilon.) Informace o porovnání dvou hodnot dvojité přesnosti s plovoucí desetinnou čárkou najdete v Double a Equals(Double).
Poznámky k platformě
V systémech ARM je hodnota Epsilon konstanty příliš malá, aby se zjistila, takže se rovná nule. Můžete definovat alternativní hodnotu epsilon, která se rovná 2,2250738585072014E-308.