Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.
Il valore della proprietà Epsilon riflette il valore più piccolo positivo Double significativo nelle operazioni numeriche o nei confronti quando il valore dell'istanza di Double è zero. Ad esempio, il codice seguente mostra che zero e Epsilon sono considerati valori diversi, mentre zero e metà del valore di Epsilon sono considerati uguali.
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
Più precisamente, il formato a virgola mobile è costituito da un segno, una mantissa o un significando a 52 bit e un esponente a 11 bit. Come illustrato nell'esempio seguente, zero ha un esponente di -1022 e una mantissa pari a 0. Epsilon ha un esponente di -1022 e una mantissa di 1. Ciò significa che Epsilon è il più piccolo valore positivo Double maggiore di zero e rappresenta il valore più piccolo possibile e il più piccolo incremento possibile per un Double il cui esponente è -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
Tuttavia, la proprietà Epsilon non è una misura generale della precisione del tipo di Double; si applica solo alle istanze di Double con valore zero o esponente pari a -1022.
Nota
Il valore della proprietà Epsilon non equivale a machine epsilon, che rappresenta il limite superiore dell'errore relativo dovuto all'arrotondamento nell'aritmetica a virgola mobile.
Il valore di questa costante è 4,94065645841247e-324.
Due numeri a virgola mobile apparentemente equivalenti potrebbero non essere confrontati a causa delle differenze nelle cifre meno significative. Ad esempio, l'espressione C#, (double)1/3 == (double)0.33333
, non viene confrontata come uguale perché l'operazione di divisione sul lato sinistro ha la precisione massima mentre la costante sul lato destro è precisa solo per le cifre specificate. Se si crea un algoritmo personalizzato che determina se due numeri a virgola mobile possono essere considerati uguali, non è consigliabile basare l'algoritmo sul valore della costante Epsilon per stabilire il margine assoluto accettabile di differenza per i due valori da considerare uguali. In genere, tale margine di differenza è molte volte maggiore di Epsilon. Per informazioni sul confronto di due valori a virgola mobile e precisione doppia, vedere Double e Equals(Double).
Note sulla piattaforma
Nei sistemi ARM, il valore della costante Epsilon è troppo piccolo da rilevare, quindi equivale a zero. È possibile definire un valore di epsilon alternativo uguale a 2,2250738585072014E-308.