Почему этот код возвращает разные значения? (С# и VB.NET)

Код VB.NET:

Module Module1

Sub Main()
    Dim x, y As Single
    x = 0 + (512 / 2 - 407) / 256 * 192 * -1
    y = 0 + (512 / 2 - 474) / 256 * 192
    Console.WriteLine(x.ToString + ": " + y.ToString)
    Console.ReadLine()
End Sub

End Module

Возвращает: 113,25: -163,5

Код С#:

class Program
{
    static void Main(string[] args)
    {
        float x, y;
        x = 0 + (512 / 2 - 407) / 256 * 192 * -1;
        y = 0 + (512 / 2 - 474) / 256 * 192;
        Console.WriteLine(x + ": " + y);
        Console.ReadLine();
    }
}

возвращает 0: 0

Я не понимаю, буду признателен за объяснение.

Ответ 1

С# / выполняет целочисленное деление, обрезая дробную часть. VB.NET неявно переходит к Double.

Чтобы выполнить деление с плавающей запятой, введите в тип с плавающей точкой:

    static void Main(string[] args)
    {
        float x, y;
        x = 0 + (512 / 2 - 407) / (float)256 * 192 * -1;
        y = 0 + (512 / 2 - 474) / (float)256 * 192;
        Console.WriteLine(x + ": " + y);
        Console.ReadLine();
    }

Ответ 2

Линии С#, такие как 0 и 512, имеют тип int. Любой int/int (int, деленный на int) приводит к целочисленному делению, которое отбрасывает любой дробный остаток, теряя точность. Если вместо 512 вместо 0 и 512F использовать float-литеры, например 0F, то С# будет выполнять деление с плавающей запятой, которое сохранит дробную часть.

static void Main(string[] args)
{
    float x, y;
    x = 0F + (512F / 2F - 407F) / 256F * 192F * -1F;
    y = 0F + (512F / 2F - 474F) / 256F * 192F;
    Console.WriteLine(x + ": " + y);
    Console.ReadLine();
}