Змінюй хід війни! Допомагай ЗСУ!

Нужна помошь в C# ну или вообще програмиста

🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
Статус: Offline
Реєстрація: 31.01.2008
Повідом.: 70
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #1
Нужна помошь в C# ну или вообще програмиста

Вообщем вопрос такой... нужно написать прогу - кредитный калькулятор..... Не могу расчитать сроки выплаты при динамическом погашении кредита (т.е. когда с каждой выплатой сумма кредита уменьшается)... Формула выглядит примерно так:
платеж в месяц составит:
1 мес. - (сумма/срок)+(сумма*%/100)
2 мес. - (остаток(т.е. сумма минус выплата за первый мес)/срок)+(остаток*%/100) ........... и.т.д.
Внимание вопрос! Как это реализовать циклом??? что-то совсем в голову не лезет... видать перетрудился:confused:

з.ы. при этом все промежуточные значения, т.е. остатки после каждого месяца и суммы выплат должны выводиться на экран
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #2
рекурсивный вызов функции содержащей (сумма/срок)+(сумма*%/100) в цикле
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #3
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #4
int period = 12; //период кредитования
double kreditSum = 1000; //сумма кредита
double kreditRate = 0.2; //ставка по кредиту
double paidSum = 0; //погашено кредита
for (int month = 1; month <= period; month++) {
double rest = kreditSum - paidSum; //остаток по кредиту на текущий месяц
double paid = (rest/kreditSum) + (rest*kreditRate/100); //выплата по кредиту за текущий месяц
paidSum += paid;
}

Обычный цикл, без рекурсий, думаю, проблем с адаптацией кода возникнуть не должно.
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #5
lomachka ща проверю отпишусь... но заранее спасибо за совет

все работает, но выдает неправильные результаты.. получается что платишь ментше чем взял))) фигня... вообщем пошел спать, на свежую голову утром посмотрю.. спасибо за помощь
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #6
:D подскажи, в каком банке работаешь? Пойду у вас кредит брать...
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #7
девушка, ну кто же объявляет переменные в цикле.
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #8
девушка, ну кто же объявляет переменные в цикле.
Я нигде не видела запрета на объявление переменных в цикле, а основная рекоммендация по объявлению переменных - "объявляйте переменные там где они нужны". В данном случае мне нужны результаты рассчетов внутри цикла и я ограничиваю область видимости этих переменных циклом. Если Вам больше нравится объявлять все переменные перед циклом - пожалуйста, но мне такой подход не по душе.
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #9
int period = 12; //период кредитования
double kreditSum = 1000; //сумма кредита
double kreditRate = 0.2; //ставка по кредиту
double paidSum = 0; //погашено кредита
for (int month = 1; month <= period; month++) {
double rest = kreditSum - paidSum; //остаток по кредиту на текущий месяц
double paid = (rest/kreditSum) + (rest*kreditRate/100); //выплата по кредиту за текущий месяц
paidSum += paid;
}

Обычный цикл, без рекурсий, думаю, проблем с адаптацией кода возникнуть не должно.

нес овсем так. вы не учли срок кредитования (или это не без срочный кредит) и переменную "погашено кредита" нужно привязывать к месяцам, т.к. в условии не оговорено что сумма погашения будет равной.

п.с. поэтому и предложения пошли кредиты - у вас брать ;)
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #10
девушка, ну кто же объявляет переменные в цикле.

ну ошибка здесь не в этом. т.к. указанные переменные используются лишь в пределах одной итерации.

int period = 12; //период кредитования
double kreditSum = 1000; //сумма кредита
double kreditRate = 0.2; //ставка по кредиту
double paidSum = 0; //погашено кредита
for (int month = 1; month <= period; month++) {
double rest = kreditSum - paidSum; //остаток по кредиту на текущий месяц
double paid = (rest/kreditSum) + (rest*kreditRate/100); //выплата по кредиту за текущий месяц
paidSum += paid;
}
исходя из формул ТС ошибка находится здесь (выделил в коде) у автора там находится период а не сумма кредита.

выдает неправильные результаты.. получается что платишь ментше чем взял)))
1 мес. - (сумма/срок)+(сумма*%/100)
2 мес. - (остаток(т.е. сумма минус выплата за первый мес)/срок)+(остаток*%/100) ........... и.т.д.

А тут видимо ошибка у Вас во второй формуле:
возможно в первой скобке необходимо брать сумма/срок а не остаток/срок. таким образом с каждым месяцем будет падать выплата процента но база оставаться на месте. В Вашем случае база тоже уменьшается.

Итого:
Код:
int period = 12; //период кредитования
double kreditSum = 1000; //сумма кредита
double kreditRate = 0.2; //ставка по кредиту
double paidSum = 0; //погашено кредита

for (int month = 1; month <= period; month++)
{
   double rest = kreditSum - paidSum; //остаток по кредиту на текущий месяц
   double paid = (kreditSum / period) + (rest * kreditRate / 100); //выплата по кредиту за текущий месяц
   Console.WriteLine("{0}", paid);
   paidSum += paid;
}

Console.WriteLine("Sum: {0}", paidSum);
Console.ReadKey();
Результат:
85,3333333333333
85,1626666666667
84,9923413333333
84,8223566506667
84,6527119373653
84,4834065134906
84,3144397004636
84,1458108210627
83,9775191994206
83,8095641610217
83,6419450326997
83,4746611426343
Sum: 1012,81075649216
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #11
lomachka ща проверю отпишусь... но заранее спасибо за совет

все работает, но выдает неправильные результаты.. получается что платишь ментше чем взял))) фигня... вообщем пошел спать, на свежую голову утром посмотрю.. спасибо за помощь

в коде ошибка
double paid = (rest/kreditSum) + (rest*kreditRate/100)
нужно делить на срок
double paid = (rest/period) + (rest*kreditRate/100)

И еще, если у Вас выплаты по телу кредита постоянны, тогда код примет вид:

int period = 12; //период кредитования
double kreditSum = 1000; //сумма кредита
double kreditRate = 0.2; //ставка по кредиту
double monthCreditPaid = kreditSum/period; //ежемесячный платеж по телу кредита
double paidSum = 0; //погашено кредита
double bodyPaidSum = 0; //погашено тела кредита

for (int month = 1; month <= period; month++) {
double rest = kreditSum - bodyPaidSum; //остаток по кредиту на текущий месяц
double paid = monthCreditPaid + ((rest*kreditRate)/100); //выплата по кредиту за текущий месяц
bodyPaidSum += monthCreditPaid;
paidSum += paid;
}

но если у Вас изменяется платеж именно по телу кредита - проверьте правильность формулы.

:))))) долго сплю
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #12
Вообщем вопрос такой... нужно написать прогу - кредитный калькулятор..... Не могу расчитать сроки выплаты при динамическом погашении кредита (т.е. когда с каждой выплатой сумма кредита уменьшается)...
Внимание вопрос! Как это реализовать циклом??? что-то совсем в голову не лезет... видать перетрудился:confused:

з.ы. при этом все промежуточные значения, т.е. остатки после каждого месяца и суммы выплат должны выводиться на экран

а на который срок?
если на год-два (в смысле, не ипотека), то проще в Экселе за пару минут ячейки формулами связать и всё ...
не забивайте микроскопом гвозди ... :)
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #13
а на который срок?
если на год-два (в смысле, не ипотека), то проще в Экселе за пару минут ячейки формулами связать и всё ...
не забивайте микроскопом гвозди ... :)

"Инквизиция вправе удивляться, почему я забиваю гвозди микроскопом, да... Но никак не обвинять меня в этом!" © С.Лукьяненко Дневной дозор
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #14
"Инквизиция вправе удивляться, почему я забиваю гвозди микроскопом, да... Но никак не обвинять меня в этом!" © С.Лукьяненко Дневной дозор

:клас:

а вообще, сорри ...
пропустил в старт-посте требование, что нужно написать именно прогу ...
подумал, типа, для личного пользования что-нить ... не подумал, что это может быть заданием в ВУЗе, скажем ...
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #15
по double сразу видно что писать код для денежных расчетов никогда не приходилось :) В таких случаях Decimal используют

девушка, ну кто же объявляет переменные в цикле.

вот именно в C# выносить определение переменной из цикла как-раз и не следует, это может привести к снижению производительности ;) Так что девушка оказалась опытнее вас :D

P.S.: Вот мой вариант :)
Код:
            Decimal credit = 1000M;         // Сумма кредита
            Decimal period = 12M;         // Срок кредита
            Decimal rate = 15.0M;           // Процентная ставка

            Decimal body = credit;          // Тело кредита
            Decimal totalSum = 0M;          // Сумма выплат по кредиту
            Decimal paidMonth = Math.Round(body / period, 2); // Месячный платеж

            while (Math.Round(body,2) > 0)
            {
                // выплата по телу кредита:
                Decimal paidBody = paidMonth > body ? body : paidMonth;
                // выплата процентов на тело кредита:
                Decimal paidPercent = Math.Round((body * rate) / 100M, 2);

                totalSum += paidBody + paidPercent;
                Console.WriteLine("body={0}\tpaid={1}\tpercent={2}\tSum={3}", Math.Round(body, 2), Math.Round(paidBody, 2), Math.Round(paidPercent, 2), Math.Round(totalSum, 2));
                body -= paidBody;
            }

            Console.WriteLine("======");
            Console.WriteLine("Total Paid Sum: {0}", Math.Round(totalSum, 2));
            Console.WriteLine("Overpaid: {0}", Math.Round(totalSum-credit, 2));
            Console.ReadKey();

Код:
body=1000       paid=83.33      percent=150.0   Sum=233.33
body=916.67     paid=83.33      percent=137.50  Sum=454.16
body=833.34     paid=83.33      percent=125.00  Sum=662.49
body=750.01     paid=83.33      percent=112.50  Sum=858.32
body=666.68     paid=83.33      percent=100.00  Sum=1041.65
body=583.35     paid=83.33      percent=87.50   Sum=1212.48
body=500.02     paid=83.33      percent=75.00   Sum=1370.81
body=416.69     paid=83.33      percent=62.50   Sum=1516.64
body=333.36     paid=83.33      percent=50.00   Sum=1649.97
body=250.03     paid=83.33      percent=37.50   Sum=1770.80
body=166.70     paid=83.33      percent=25.00   Sum=1879.13
body=83.37      paid=83.33      percent=12.51   Sum=1974.97
body=0.04       paid=0.04       percent=0.01    Sum=1975.02
======
Total Paid Sum: 1975.02
Overpaid: 975.02
 
Останнє редагування:
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #16
В жизни не поверю в это. Не в то, что она опытнее, а в то, что вы правы.

Написал программку, которая последовательно запускает 2 метода:
оба содержат циклы с большим числом итераций, при чем первый метод содержит внутри переменную (с её инициализацией), а во втором эта же переменная инициализируется до цикла, но в каждой итерации идёт присваивание её значения.

также оба эти метода замеряют разницу во времени перед началом цикла и после его завершения, дабы узнать длительность.
на небольших итерациях (до 1 миллиона) разницы не было.
но вот при 1000000000 итераций, длительность была следующая:
24741415
24671411

надеюсь, не нужно объяснять, какой метод дольше работал.

Так что проверяйте свои аргументы перед тем, как кого-то учить.
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #17
В жизни не поверю в это. Не в то, что она опытнее, а в то, что вы правы.

вообще-то это рекомендация микрософта - не заниматься подобными "оптимизациями" в C#, и вообще древнейший баян (то что в C# подобная оптимизация приносит только вред). Есть соответствующая тема на RSDN, гдето 3-4 летней давности. Там подробно этот вопрос исследован.
Если коротко, то когда ты декларацию переменной не выносишь за тело цикла, оптимизатор компилятора видит узкую область видимости переменной и сделает все оптимальным образом, а вот если ты вынесешь за тело цикла, то оптимизатор увидит что переменная имеет большую область видимости и возможностей для оптимизации у него уже будет меньше.

Не поленись откопать эту тему на RSDN, там сотни умнейших людей, наступивших как и ты на эти грабли все разложили по полочкам, от и до. Начиная от тестов, и заканчивая выводами почему так происходит. ;)

Написал программку, которая последовательно запускает 2 метода:
оба содержат циклы с большим числом итерацийно вот при 1000000000 итераций, длительность была следующая:
24741415
24671411

надеюсь, не нужно объяснять, какой метод дольше работал.

во первых ответьте на вопрос - на каком языке вы проводили этот тест? на C#? или это был вообще не дотнет? Мои слова касались именно дотнета!
Во вторых - давайте сюда исходник теста, чтобы не говорить об абстрактном софте с непонятными цифрами... ;)

Так что проверяйте свои аргументы перед тем, как кого-то учить.

Ну если гуглом пользоваться не умеете, я вам подкину тему с RSDN, читайте:
Посилання видалено

На этой же сортировке с удивлением обнаружил, что цикл for(int i = 0;
i < arr.Length; ++i) выполняется быстрее, чем если длину массива
записать в отдельную переменную
... (после вынесения arr.Length в
отдельную переменную время сортировки увеличилось с 86 до 116 сек).

Но на семинаре по гайдам МС всегда приводят эту строку в пример — говорят, не пытайтесь думать за компилятор — он неплохо соображает и знает что делать...

просвещайтесь :)

Кстати, что касается касается самой декларации, то в C# вообще нет никакой разницы, где определена переменная, вне тела цикла или внутри. Чтобы доказать это, делаем две тестовых программки:

1.cs:
Код:
using System;

class Program
{
	static void Main()
	{
	    int sum = 0;
        
        for(int i=0; i < 10; i++)
        {
            int a = i + i;
            sum += a;
        }
    }
}

2.cs:
Код:
using System;

class Program
{
	static void Main()
	{
	    int sum = 0, a;
        
        for(int i=0; i < 10; i++)
        {
            a = i + i;
            sum += a;
        }
    }
}

Сравниваем что получилось после компиляции:

1.il:
Код:
.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 num,
        [1] int32 num2,
        [2] int32 num3,
        [3] bool flag)
    L_0000: nop 
    L_0001: ldc.i4.0 
    L_0002: stloc.0 
    L_0003: ldc.i4.0 
    L_0004: stloc.1 
    L_0005: br.s L_0015
    L_0007: nop 
    L_0008: ldloc.1 
    L_0009: ldloc.1 
    L_000a: add 
    L_000b: stloc.2 
    L_000c: ldloc.0 
    L_000d: ldloc.2 
    L_000e: add 
    L_000f: stloc.0 
    L_0010: nop 
    L_0011: ldloc.1 
    L_0012: ldc.i4.1 
    L_0013: add 
    L_0014: stloc.1 
    L_0015: ldloc.1 
    L_0016: ldc.i4.s 10
    L_0018: clt 
    L_001a: stloc.3 
    L_001b: ldloc.3 
    L_001c: brtrue.s L_0007
    L_001e: ret 
}

2.il:
Код:
.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 num,
        [1] int32 num2,
        [2] int32 num3,
        [3] bool flag)
    L_0000: nop 
    L_0001: ldc.i4.0 
    L_0002: stloc.0 
    L_0003: ldc.i4.0 
    L_0004: stloc.2 
    L_0005: br.s L_0015
    L_0007: nop 
    L_0008: ldloc.2 
    L_0009: ldloc.2 
    L_000a: add 
    L_000b: stloc.1 
    L_000c: ldloc.0 
    L_000d: ldloc.1 
    L_000e: add 
    L_000f: stloc.0 
    L_0010: nop 
    L_0011: ldloc.2 
    L_0012: ldc.i4.1 
    L_0013: add 
    L_0014: stloc.2 
    L_0015: ldloc.2 
    L_0016: ldc.i4.s 10
    L_0018: clt 
    L_001a: stloc.3 
    L_001b: ldloc.3 
    L_001c: brtrue.s L_0007
    L_001e: ret 
}

как видим разнизца заключается только в том что ячейки поменялись местами - вместо 1-й стала 2-я, а вместо 2-й стала 1-ая. Тоесть код абсолютно одинаков, только переменные хранятся в другом порядке (это заморочки компилятора - как ему было удобнее, так и сделал). Вот и вся разница :)
 
Останнє редагування:
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #18
байт-код. а исходники давать не буду, замерь свой код, разница будет такой же.

возможно, физически разница видна только на больших промежутках времени, но тем не менее, результаты стабильны.
я завтра поговорю с одним человеком, и тогда уже смогу точно сказать, что не прав. пока что аргументов в свою пользу у меня, действительно, нет.
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #19
байт-код. а исходники давать не буду, замерь свой код, разница будет такой же.

от-жеж Фома-неверующий :D Ты будешь доказывать что время работы программы имеет сильную зависимость от того что переменную A мы будем хранить в ячейке 0, а переменную B в ячейке 1, а если наоборот то все будет работать заметно медленее? :ги:

Результат компиляции я приводил выше - разницы в коде нет!

Измеряем, для этого дополним вышеуказанный код таким образом:
Код:
using System;
using System.Diagnostics;

class Program
{
	static void Main()
	{
	    int sum = 0;

        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        for (long j = 0; j < 1000000000; j++)       // loop to minimize measurement error
            for (int i = 0; i < 10; i++)
        {
            int a = i + i;
            sum += a;
        }
        stopWatch.Stop();
        Console.WriteLine("time: {0}", stopWatch.Elapsed);
    }
}

аналогичо для кода 2.cs, а теперь результаты:
D:\SRC>1.exe
time: 00:00:11.9287992

D:\SRC>2.exe
time: 00:00:11.9321692

итого, если декларацию не выносить, то работает быстрее :D Шутка, на самом деле время одинаковое, разница объясняется погрешностью измерений и многопоточностью windows :)
 
  • 🟡 21:35 Відбій тривоги в Харківський район.Зверніть увагу, тривога ще триває у:- Харківський район#Харківський_район
  • #20
Планировщиком виндоус.

Разница-то объясняется, но почему тогда именно второе (либо первое) значение больше второго? почему они не колеблются?
 
Назад
Зверху Знизу