Aquí hay un fragmento interesante de la especificación C#, de la sección 4.1.6:
operaciones de coma flotante pueden realizaron con mayor precisión que el tipo de resultado de la operación. Para ejemplo, algunas arquitecturas de hardware apoyan una o escribe de punto flotante “extendida” “de largo doble” con una mayor gama y precisión que el tipo doble, e implícitamente realizar todas las operaciones de punto flotante utilizando este tipo superior de precisión . Sólo al coste excesivo en el rendimiento se puede hacer este tipo de arquitecturas hardware para realizar operaciones de punto flotante con menos precisión, y en lugar de requiere una implementación que renunciar a tanto el rendimiento y la precisión, C# permite un mayor tipo de precisión que deben utilizado para todas las operaciones de punto flotante . Además de entregar más resultados precisos de , esto raramente tiene ningún efecto mensurable .
Es posible que este sea uno de los "efectos medibles" gracias a esa llamada a Techo. Tomando el techo de un número de punto flotante, como han notado otros, aumenta una diferencia de 0.000000002 en nueve órdenes de magnitud porque convierte 15.99999999 en 16 y 16.00000001 en 17. Dos números que difieren ligeramente antes de la operación difieren enormemente después; la pequeña diferencia puede explicarse por el hecho de que diferentes máquinas pueden tener más o menos "precisión extra" en sus operaciones de punto flotante.
algunos temas relacionados:
Para abordar el problema concreto de cómo calcular una relación de aspecto de un flotador: Me posiblemente resolver esto de una manera completamente diferente. Me gustaría hacer una tabla como la siguiente:
struct Ratio
{
public int X { get; private set; }
public int Y { get; private set; }
public Ratio (int x, int y) : this()
{
this.X = x;
this.Y = y;
}
public double AsDouble() { return (double)X/(double)Y; }
}
Ratio[] commonRatios = {
new Ratio(16, 9),
new Ratio(4, 3),
// ... and so on, maybe the few hundred most common ratios here.
// since you are pinning results to be less than 20, there cannot possibly
// be more than a few hundred.
};
y ahora su implementación es
public string AspectRatioAsString(double ratio)
{
var results = from commonRatio in commonRatios
select new {
Ratio = commonRatio,
Diff = Math.Abs(ratio - commonRatio.AsDouble())};
var smallestResult = results.Min(x=>x.Diff);
return String.Format("{0}:{1}", smallestResult.Ratio.X, smallestResult.Ratio.Y);
}
Aviso cómo el código ahora se parece mucho a la operación que está intentando realizar: a partir de esta lista de común ratios, elija el que minimice la diferencia entre la relación dada y la razón común.
¿Alguna razón por la que está aprobando el asterisco como un flotador en lugar de un doble? –
@Oded - lo siento, borré mi comentario, decidí promocionarlo a una respuesta. – ChrisF
Consejo rápido: (doble) 0.1 es un poco desperdicio. Deberías reemplazarlo por 0.1 (que por defecto es doble) o 0.1d si quieres ser explícito. No estoy seguro de si el compilador lo convierte en un doble, pero esto podría ahorrarle un molde ... –