Не могу убрать лишний вывод C#
Уже голову сломал, по несколько раз переписывал программу с нуля, менял условие и в итоге ничего не меняется. В программе идет итерация по промежутку от а до b с шагом табуляции и в консоль нужно вывести все значения которые принимает функция. Вот вывод программы:
a = -0,9; b = -0,4; h = 0,05
Input a = -0,9
Input b = -0,4
Input h = 0,05
x = -0,90 y = -0,62993
x = -0,85 y = -0,55074
x = -0,80 y = -0,47320
x = -0,75 y = -0,39922
x = -0,70 y = -1,77059
x = -0,65 y = -1,87475
x = -0,60 y = 2,65673
x = -0,55 y = 3,20433
x = -0,50 y = 3,91632
x = -0,45 y = 4,87059
x = -0,40 y = 4,87059
В конечном итоге нужно убрать из вывода последнюю итерацию в x = -0,4.
Вот код:
using System;
using static System.Math;
namespace Program
{
class Programm
{
public static void Main(string[] args)
{
Console.WriteLine("a = -0,9; b = -0,4; h = 0,05");
Lab2_a lab = new Lab2_a();
lab.Input();
lab.cycle();
lab.Output();
}
}
class Lab2_a : Znach
{
public void Input()
{
Console.Write("Input a = ");
a = Convert.ToDouble(Console.ReadLine());
Console.Write("Input b = ");
b = Convert.ToDouble(Console.ReadLine());
Console.Write("Input h = ");
h = Convert.ToDouble(Console.ReadLine());
}
public override void Output()
{
Console.WriteLine("x = {0:F2}\t y = {1:F5}", x, y);
}
}
abstract class Znach
{
public double a, b, x, y, h;
public void cycle()
{
for(x = a; x <= b; x += h)
{
if (x <= -0.7)
{
y = Atan(Pow(x, 3));
}
else if (x > -0.7 && x <= -0.6)
{
y = Tan(x + Math.Log(Math.Abs(x)));
}
else
{
y = 1 /Tan(Pow(x, 2));
}
Output();
}
}
public abstract void Output();
}
}
Ответы (2 шт):
Если изменить
Console.WriteLine("x = {0:F2}\t y = {1:F5}", x, y);
на
Console.WriteLine("x = {0:R}\t y = {1:R}", x, y);
то можно заметить, что x = -0,40 на самом деле x = -0.39999999999999974.
https://ru.stackoverflow.com/a/417454/299581
Все, что я написал выше, конечно, интересно, но...
lab.Input();
lab.cycle();
lab.Output();
В lab.cycle уже есть Output(), дополнительно вызывать его после lab.cycle() не нужно.
Если в приведенном вами коде убрать дополнительный lab.Output(), то x = -0,4 "уберется".
Также нужно использовать строгое неравенство.
А если вы хотите, чтобы x был включительно до b, то можно использовать информацию из ссылки выше и делать сравнение с допуском: (x - b) < 0.001.
Дело в точности вычислений. Чтобы работало лучше, стоит посчитать число шагов заранее и использовать умножение, а не сложение: tio.run
double a = -0.9, b = -0.4, h = 0.05;
for (int i=0, n=(int)((b-a)/h); i<n; ++i)
{
var x = a + i * h;
Console.WriteLine("{0:0.00}", x);
}
Console.WriteLine();
for (int i=0, n=(int)((b-a)/h); i<=n; ++i)
{
var x = a + i * h;
Console.WriteLine("{0:0.00}", x);
}
Я не стал использовать округление из-за того, что у тебя данные вводятся пользователем и нет гарантии, что разность делится нацело. Возможно, тут всё равно стоит какой-то эпсилон добавить, чтобы компенсировать возможные погрешности, но я не уверен. Если бы было гарантированно известно, что должно быть деление нацело, я бы округлил математически.