System.Single.Epsilon-Eigenschaft
Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.
Der Wert der Epsilon Eigenschaft gibt den kleinsten positiven Single Wert wieder, der bei numerischen Vorgängen oder Vergleichen signifikant ist, wenn der Wert der Single Instanz null ist. Der folgende Code zeigt beispielsweise, dass Null und Epsilon als ungleiche Werte betrachtet werden, während null und die Hälfte des Werts Epsilon als gleich angesehen werden.
using System;
public class Example1
{
public static void Main()
{
float[] values = { 0f, Single.Epsilon, Single.Epsilon * .5f };
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 = 1.401298E-45: False
// 0 = 0: True
//
// 1.401298E-45 = 0: False
open System
let values = [ 0f; Single.Epsilon; Single.Epsilon * 0.5f ]
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 = 1.401298E-45: False
// 0 = 0: True
//
// 1.401298E-45 = 0: False
Module Example1
Public Sub Main()
Dim values() As Single = {0, Single.Epsilon, Single.Epsilon * 0.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 = 1.401298E-45: False
' 0 = 0: True
'
' 1.401298E-45 = 0: False
Genauer gesagt besteht das Gleitkommaformat mit einfacher Genauigkeit aus einem Zeichen, einer 23-Bit-Mantissa oder einem Significand und einem 8-Bit-Exponenten. Wie das folgende Beispiel zeigt, hat Null einen Exponenten von -126 und eine Mantissa von 0. Epsilon hat einen Exponenten von -126 und eine Mantissa von 1. Dies bedeutet, dass Single.Epsilon es sich um den kleinsten positiven Single Wert handelt, der größer als Null ist und den kleinsten möglichen Wert und den kleinsten möglichen Inkrement für einen Single Exponenten darstellt, dessen Exponent -126 ist.
using System;
public class Example2
{
public static void Main()
{
float[] values = { 0.0f, Single.Epsilon };
foreach (var value in values) {
Console.WriteLine(GetComponentParts(value));
Console.WriteLine();
}
}
private static string GetComponentParts(float value)
{
string result = String.Format("{0:R}: ", value);
int indent = result.Length;
// Convert the single to a 4-byte array.
byte[] bytes = BitConverter.GetBytes(value);
int formattedSingle = BitConverter.ToInt32(bytes, 0);
// Get the sign bit (byte 3, bit 7).
result += String.Format("Sign: {0}\n",
(formattedSingle >> 31) != 0 ? "1 (-)" : "0 (+)");
// Get the exponent (byte 2 bit 7 to byte 3, bits 6)
int exponent = (formattedSingle >> 23) & 0x000000FF;
int adjustment = (exponent != 0) ? 127 : 126;
result += String.Format("{0}Exponent: 0x{1:X4} ({1})\n", new String(' ', indent), exponent - adjustment);
// Get the significand (bits 0-22)
long significand = exponent != 0 ?
((formattedSingle & 0x007FFFFF) | 0x800000) :
(formattedSingle & 0x007FFFFF);
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: 0xFFFFFF82 (-126)
// Mantissa: 0x0000000000000
//
//
// 1.401298E-45: Sign: 0 (+)
// Exponent: 0xFFFFFF82 (-126)
// Mantissa: 0x0000000000001
open System
let getComponentParts (value: float32) =
let result = $"{value:R}: "
let indent = result.Length
// Convert the single to a 4-byte array.
let bytes = BitConverter.GetBytes value
let formattedSingle = BitConverter.ToInt32(bytes, 0)
// Get the sign bit (byte 3, bit 7).
let result = result + $"""Sign: {if formattedSingle >>> 31 <> 0 then "1 (-)" else "0 (+)"}\n"""
// Get the exponent (byte 2 bit 7 to byte 3, bits 6)
let exponent = (formattedSingle >>> 23) &&& 0x000000FF
let adjustment = if exponent <> 0 then 127 else 126
let result = result + $"{String(' ', indent)}Exponent: 0x{1:X4} ({exponent - adjustment})\n"
// Get the significand (bits 0-22)
let significand =
if exponent <> 0 then
(formattedSingle &&& 0x007FFFFF) ||| 0x800000
else
formattedSingle &&& 0x007FFFFF
result + $"{String(' ', indent)}Mantissa: 0x{significand:X13}\n"
let values = [ 0f; Single.Epsilon ]
for value in values do
printfn $"{getComponentParts value}\n"
// // The example displays the following output:
// 0: Sign: 0 (+)
// Exponent: 0xFFFFFF82 (-126)
// Mantissa: 0x0000000000000
//
//
// 1.401298E-45: Sign: 0 (+)
// Exponent: 0xFFFFFF82 (-126)
// Mantissa: 0x0000000000001
Module Example2
Public Sub Main()
Dim values() As Single = {0.0, Single.Epsilon}
For Each value In values
Console.WriteLine(GetComponentParts(value))
Console.WriteLine()
Next
End Sub
Private Function GetComponentParts(value As Single) As String
Dim result As String = String.Format("{0:R}: ", value)
Dim indent As Integer = result.Length
' Convert the single to an 8-byte array.
Dim bytes() As Byte = BitConverter.GetBytes(value)
Dim formattedSingle As Integer = BitConverter.ToInt32(bytes, 0)
' Get the sign bit (byte 3, bit 7).
result += String.Format("Sign: {0}{1}",
If(formattedSingle >> 31 <> 0, "1 (-)", "0 (+)"),
vbCrLf)
' Get the exponent (byte 2 bit 7 to byte 3, bits 6)
Dim exponent As Integer = (formattedSingle >> 23) And &HFF
Dim adjustment As Integer = If(exponent <> 0, 127, 126)
result += String.Format("{0}Exponent: 0x{1:X4} ({1}){2}",
New String(" "c, indent), exponent - adjustment,
vbCrLf)
' Get the significand (bits 0-22)
Dim significand As Long = If(exponent <> 0,
(formattedSingle And &H7FFFFF) Or &H800000,
formattedSingle And &H7FFFFF)
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: 0xFFFFFF82 (-126)
' Mantissa: 0x0000000000000
'
'
' 1.401298E-45: Sign: 0 (+)
' Exponent: 0xFFFFFF82 (-126)
' Mantissa: 0x0000000000001
Die Epsilon Eigenschaft ist jedoch kein allgemeines Maß für die Genauigkeit des Single Typs. Sie gilt nur für Single Instanzen mit dem Wert Null.
Hinweis
Der Wert der Epsilon Eigenschaft entspricht nicht der Maschine epsilon, die die obere Grenze des relativen Fehlers darstellt, da sie in Gleitkommaarithmetik gerundet wird.
Der Wert dieser Konstante ist 1,4e-45.
Zwei scheinbar gleichwertige Gleitkommazahlen können aufgrund von Unterschieden in ihren am wenigsten signifikanten Ziffern nicht gleich verglichen werden. Beispielsweise wird der C#-Ausdruck nicht gleich verglichen, (float)1/3 == (float)0.33333
da der Divisionsvorgang auf der linken Seite die maximale Genauigkeit aufweist, während die Konstante auf der rechten Seite nur für die angegebenen Ziffern genau ist. Wenn Sie einen benutzerdefinierten Algorithmus erstellen, der bestimmt, ob zwei Gleitkommazahlen gleich sein können, müssen Sie einen Wert verwenden, der größer als die Epsilon Konstante ist, um den zulässigen absoluten Differenzrand für die beiden Werte festzulegen, die gleich sind. (In der Regel ist dieser Differenzrand mehrmals größer als Epsilon.)
Plattformnotizen
Auf ARM-Systemen ist der Wert der Epsilon Konstante zu klein, um erkannt zu werden, sodass er null entspricht. Sie können stattdessen einen alternativen Epsilonwert definieren, der 1,175494351E-38 entspricht.