0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
1

Ошибка в результатах при подсчете суммы n-1 членов прогрессии

20.06.2012, 11:56. Показов 1847. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Проблема собственно вот в чем: разница в результатах при подсчете суммы n-1 членов прогрессии.
Текст задания:
Составить программу, вычисляющую сумму возрастающей арифметической прогрессии прямым суммированием слагаемых. Определить минимальное число слагаемых, нужных для переполнения двойного слова. Программа не должна выдавать ошибку переполнения. С клавиатуры задается начальный член и шаг прогрессии.
Ниже приведу коды на ассемблере и паскале,т.к. по заданию нужно написать на этих языках.


Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
.model small
.data
str1 db 13,10,'Программа вычисляет сумму арифметической прогрессии'
     db 13,10,'Введите шаг прогрессии(d): $'
str2 db 13,10,'Введите начальное число прогрессии(a1): $'
a1 dd 0                  ;начальный элемент прогрессии
d  dd 0                  ;шаг прогрессии
n  dd 1                  ;минимальное количество слагаемых для переполнения
str3 db 13,10,'Минимальное число слагаемых для переполнения: '
d1   db 10 dup (' '),'$'
str5 db 13,10,'Сумма n-1 первых членов прогрессии равна: '
d2   db 10 dup (' '),'$'
buf  db 11, 13 dup(0)    ;принимает строку, введенную с клавиатуры
 
 
.stack 256
.code
start:
.386
  mov ax,@data           ;настраиваем сегментные регистры
  mov ds,ax
  mov es,ax
vvd: mov dx, offset str1 ;выводим приглашение
 call InputNumber        ;вводим шаг прогрессии
  mov d,eax              ;сохраняем d
  test eax,eax           ;если введено число меньше 1, то попросим ввести снова
 jng vvd
vva1: mov dx, offset str2;выводим приглашение
 call InputNumber        ;вводим начальное число прогрессии
  mov a1,eax             ;сохраняем d
  test eax,eax           ;если введено число меньше 1, то попросим ввести снова
 jng vva1
 
  mov ebx,0              ;сумма (sum:=0)
  mov ecx,1              ;n:=1
lp1: 
  mov eax,ecx            ;передаем n в eax
  dec eax                ;n-1
  mov edx,d
  mul edx                ;(n-1)*d
  mov edx,a1
  add eax,edx            ;(n-1)*d+a1
  inc ecx   ;n:=n+1
  add ebx,eax            ;sum:=sum+a1+(n-1)*d;
 jns lp1                 ;Если не произошло переполнения в бит знака (как в паскале), то продолжаем
                         ;Если jns заменить на jnc, то вместо знакового переполнения будет отслеживаться
                         ;переполнение в признак переноса, т.е. сумма будет представлена как беззнаковое
                         ;число (2-й режим)
  dec ecx                ;поскольку приращение n перед проверкой на переполнение, то после цикла в ecx буде на 1 больше, чем надо. Вот и корректируем его.
  mov n,ecx              ;сохраняем минимальное количество слагаемых для переполнения
  mov eax,ecx            ;преобразовываем минимальное количество слагаемых для переполнения в текст
  mov edi,offset d1
 call printdec32
  mov dx,offset str3     ;выводим результат на экран
  mov ah,9
  int 21h
  mov esi,n              ;кол-во слагаемых
  mov ebx,0              ;сумма (sum:=0)
  mov ecx,1              ;n:=1
lp2:
  mov eax,ecx            ;передаем n в eax
  dec eax                ;n-1
  mov edx,d
  mul edx                ;(n-1)*d
  mov edx,a1
  add eax,edx            ;(n-1)*d+a1
  add ebx,eax            ;sum:=sum+a1+(n-1)*d
  inc ecx                ;n:=n+1
  cmp ecx,esi  ;n<=n1
 jle lp2                 ;если да, то продолжаем суммировать
  mov eax,ebx            ;преобразовываем сумму в текст
  mov edi,offset d2
 call printdec32
  mov dx,offset str5     ;выводим результат на экран
  mov ah,9
  int 21h
  
  mov ah,1               ;ожидаем нажатия любой клавиши
  int 21h
 
ex:
  mov ax,4c00h           ;выход из программы
  int 21h
 
 
str2dw proc
                         ;Преобразование строки в число
                         ;на входе ds:si ссылается на ASCIIZ строку, которую нужно преобразовать
                         ; на выходе в eax - число.
  push edx
  push esi
  xor edx,edx            ;сумма
@lp1: 
  xor eax,eax
  lodsb                  ;берем символ
  test al,al             ;если это нулевой байт, то заканчиваем
  jz @ex
  cmp al,'9'             ;Если это не цифра, то пропускаем
  jnbe @lp1
  cmp al,'0'             ;Если это не цифра, то пропускаем
  jb @lp1
  sub eax,'0'            ;получаем цифровое значение
  shl edx,1              ;умножаем сумму на 10
  add eax, edx
  shl edx,2
  add edx, eax           ;прибавляем текущее значение
  jmp @lp1
 
@ex: 
  mov eax,edx
  pop esi
  pop edx
  ret
str2dw endp
 
InputNumber proc         ; функция выводит на экран сообщение и ожидает ввода числа
                         ; ds:dx - сообщение, которое следует вывести
                         ; возвращает:
                         ; eax - введенное число
  push dx                ; сохраняем регистры
  push si
  push di
  mov ah,9
  int 21h
 
  mov ah,0ah
  mov dx,offset buf
  int 21h                ;пользователь вводит в текстовом виде в buf значение элемента массива
 
  mov di,offset buf+1
  mov al,[di]            ;берем длину введенной строки
  mov ah,0               ;ах=длине
  inc di                 ;начало введенной строки в памяти
  mov si,di              ;сохраняем это значение
  add di,ax              ;конец введенной строки в памяти
  mov [di],byte ptr 0    ;ставим нулевой байт за последним символом строки
 call str2dw             ;преобразовываем строку в значение
  pop di                 ;восстанавливаем регистры
  pop si
  pop dx
  ret
InputNumber endp
 
printdec32 proc          ;преобразование числа из ах в десятичную строку по адресу es:di
                         ;eax - число
                         ;es:di - адрес буфера приемника
  push ecx               ;сохраняем регистры
  push edx
  push ebx
  mov ebx,10             ;основание системы
  XOR ecx,ecx            ;в сх будет количество цифр в десятичном числе
 
@@m1: 
  XOR edx,edx
  DIV ebx                ;делим число на степени 10
  PUSH edx               ;и сохраняем остаток от деления(коэффициенты при степенях) в стек
  INC ecx
  TEST eax,eax
  JNZ @@m1
 
@@m2: 
  POP eax
  ADD AL,'0'             ;преобразовываем число в ASCII символ
 STOSb                   ;сохраняем в буфер
  LOOP @@m2              ;все цифры
  mov al,'$'             ;добавляем метку конца строки
 stosb
  POP ebx                 ;восстанавливаем регистры
  POP edx
  POP ecx
  RET
printdec32 endp
 
 
end start

Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
program progres; {название программы}
uses wincrt; {подключение модуля}
 
var d,a1,sum,n,sum1,i:longint; {описание переменных}
  begin
   clrScr; {очистка экрана}
   REPEAT
    writeln('Программа вычисляет сумму арифметической прогрессии');
    write('Введите шаг прогрессии(d): '); {ввод шага прогрессии}
    readln(d);
   UNTIL d>0; {защита от неверно введённых данных}
   REPEAT
    write('Введите начальное число прогрессии(a1): '); {ввод начального числа прогрессии}
    readln(a1);
   UNTIL a1>0; {защита от неверно введённых данных}
         sum:=0;
   n:=1;
{ищем минимальное число слагаемых для переполнения,
прибавляя к сумме очередное значение прогрессии (прямое суммирование), 
пока не произойдет переполнения}
   WHILE sum<=MaxLongInt-(a1+(n-1)*d) do
  begin
    sum:=sum+a1+(n-1)*d; {считается сумма прогрессии}
    n:=n+1; {считается кол-во членов прогрессии}
  end;
 
    writeln('Минимальное число слагаемых для переполнения: ',n);
    write('Сумма n первых членов прогрессии равна: ',sum:10);
    readkey;
 
 
end.
Добавлено через 2 часа 51 минуту
Ошибка как я понимаю в асме, суммирует неправильно. Не могу понять где именно неправильно

Добавлено через 20 часов 21 минуту
Что прямо никто не может помочь?
0
20.06.2012, 11:56
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.06.2012, 11:56
Ответы с готовыми решениями:

Написать рекурсивную функцию нахождения n-го члена прогрессии, суммы N первых членов прогрессии
Даны первый член и знаменатель геометрической прогрессии. Написать рекурсивную функцию 1)нахождения n-го члена прогрессии 2)НАХОЖДЕНИЯ...

Написать рекурсивную функцию для нахождения заданного члена прогрессии и суммы n первых членов прогрессии
Даны первый член и знаменатель геометрической прогрессии. Написать рекурсивную функцию для нахождения: а) n-го члена прогрессии; б) суммы n...

Ошибка при подсчёте контрольной суммы
Всем здравствуйте. Вот функция, представленная производителем приборов для проверки правильности приёма-передачи команд по Com-порту: ...

7
Хочу в Исландию
 Аватар для skaa
1041 / 840 / 119
Регистрация: 10.11.2010
Сообщений: 1,630
20.06.2012, 18:50 2
Я проверил ассемблер - считает правильно, за исключением того что ecx у тебя на 1 больше, но это легко поправить, надо не mov ecx,1, а mov ecx,0, а то ещё в цикл не вошли, а уже один раз посчитали.
Сразу после выхода из цикла lp1 ecx у меня равно 46340. А чему в Паскале равно n после выхода из цикла?
0
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
21.06.2012, 10:17  [ТС] 3
Так это смотря какие значения брать. Вот скрин, верхнее окошко это паскаль, нижнее ассемблер. Видишь какая разница в результате суммы членов прогрессии, при равных значениях? Вот это и надо исправить
Миниатюры
Ошибка в результатах при подсчете суммы n-1 членов прогрессии  
0
Хочу в Исландию
 Аватар для skaa
1041 / 840 / 119
Регистрация: 10.11.2010
Сообщений: 1,630
21.06.2012, 16:34 4
Я забыл написать какие числа брал. По-моему a1=5, d=2. Это на работе, а я сегодня отгул взял.
Вижу два окна - чёрное и белое. Какое из них Паскаль выдаёт, а какое ассемблер? Завтра буду на работе - посмотрю.
0
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
21.06.2012, 16:40  [ТС] 5
skaa, Верхнее паскаль, нижнее ассемблер.
0
Хочу в Исландию
 Аватар для skaa
1041 / 840 / 119
Регистрация: 10.11.2010
Сообщений: 1,630
22.06.2012, 17:34 6
Во время второго шага первого цикла уже происходит переполнение:
1111111111+2222222222=3333333333 - в этом числе уже старший бит =1, т.е. число отрицательное, а второй цикл у тебя проходит два раза, хотя должен по логике пройти один раз. После 49 строки поставь ещё один dec ecx, и всё будет правильно.
0
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
22.06.2012, 18:55  [ТС] 7
skaa, а может вот так: после 49й строки sub ebx,eax ? т.к. цикл заного начинается, а переполнение так и остается, т.е. нужно вернуть прежнее значение, иначе оно суммируется и получается неверный результат. как ты думаешь?
0
Хочу в Исландию
 Аватар для skaa
1041 / 840 / 119
Регистрация: 10.11.2010
Сообщений: 1,630
25.06.2012, 17:18 8
Скорее всего можно и так... Проверь.
0
25.06.2012, 17:18
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.06.2012, 17:18
Помогаю со студенческими работами здесь

Составить программу вычисления суммы m первых членов арифметич. прогрессии, если известны значения первого члена и разность арифметической прогрессии
прошу помиочь составить программу вычисления суммы 150 первых членов арифметической прогрессии если a1=-200, d=0.2

Ошибка при подсчете суммы четных цифр числа
Пытаюсь найти сумму четных цифр числа, но программа работает только если все цифры числа четные, если же есть нечетные, то выдает false. ...

Ошибка в коде при подсчете суммы цифр трехзначного числа: появляются непонятные символы
Помогите) Программа должна Считать сумму цифр трехзначного числа) когда запускаешь появляются беспорядочные символы((( .model...

Найти сумму членов геометрической прогрессии, если известны её первый член, знаменатель и число членов прогрессии
Найти сумму членов геометрической прогрессии, если известны её первый член, знаменатель и число членов прогрессии. Заранее спасибо за...

Найти сумму членов арифметической прогрессии, если известны ее первый член, знаменатель и число членов прогрессии
Найти сумму членов арифметической прогрессии, если известны ее первый член, знаменатель и число членов прогрессии. 1)...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему

Редактор формул (кликните на картинку в правом углу, чтобы закрыть)
Опции темы

Новые блоги и статьи
Отличия между venv, pyenv, pyvenv, virtualenv, pipenv, conda, virtualenvwrapp­­er, poetry и другими в Python
hw_wired 13.02.2025
В Python существует множество средств для управления зависимостями и виртуальными окружениями, что порой вызывает замешательство даже у опытных разработчиков. Каждый инструмент создавался для решения. . .
Навигация с помощью React Router
hw_wired 13.02.2025
React Router - это наиболее распространенное средство для создания навигации в React-приложениях, без которого сложно представить современную веб-разработку. Когда мы разрабатываем сложное. . .
Ошибка "error:0308010C­­:dig­ital envelope routines::unsup­­ported"
hw_wired 13.02.2025
Если вы сталкиваетесь с ошибкой "error:0308010C:digital envelope routines::unsupported" при разработке Node. js приложений, то наверняка уже успели поломать голову над её решением. Эта коварная ошибка. . .
Подключение к контейнеру Docker и работа с его содержимым
hw_wired 13.02.2025
В мире современной разработки контейнеры Docker изменили подход к созданию, развертыванию и масштабированию приложений. Эта технология позволяет упаковать приложение со всеми его зависимостями в. . .
Отличия интерфейсов и типов в TypeScript
hw_wired 13.02.2025
TypeScript - мощное средство для создания качественного и поддерживаемого кода, который расширяет возможности JavaScript, добавляя систему статической типизации. В отличие от динамической типизации. . .
Async/await в циклах JavaScript
hw_wired 13.02.2025
Современная веб-разработка немыслима без асинхронного программирования. Когда приложение выполняет длительные операции - загрузку данных с сервера, чтение файлов или обработку медиа-контента, важно. . .
Git не работает на MacOS после апдейта
hw_wired 13.02.2025
После очередного обновления MacOS многие разработчики сталкиваются с неприятным сюрпризом - Git перестает работать и выдает ошибку "xcrun: error: invalid active developer path". Эта проблема особенно. . .
Git отказывается объединять несвязанные истории
hw_wired 13.02.2025
Git работает безупречно, пока мы не сталкиваемся с особыми ситуациями вроде объединения веток с разными корнями истории. В таких случаях система контроля версий может преподнести неприятный сюрприз в. . .
Проверка email с помощью JavaScript
hw_wired 13.02.2025
Email-адреса имеют довольно запутанную спецификацию, которая допускает множество неочевидных вариантов написания. Например, знали ли вы, что адрес вида "name+tag@domain. com" или даже. . .
Замена всех вхождений строки с помощью JavaScript
hw_wired 13.02.2025
JavaScript предлагает несколько способов для выполнения операций замены в строках, каждый из которых имеет свои особенности и область применения. От простейшей замены первого найденного вхождения до. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru