Форум программистов, компьютерный форум, киберфорум
Наши страницы
Assembler, MASM, TASM
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
DeemaS
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
1

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

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

Проблема собственно вот в чем: разница в результатах при подсчете суммы 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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.06.2012, 11:56
Ответы с готовыми решениями:

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

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

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

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

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

7
skaa
Хочу в Исландию
1035 / 834 / 119
Регистрация: 10.11.2010
Сообщений: 1,629
20.06.2012, 18:50 2
Я проверил ассемблер - считает правильно, за исключением того что ecx у тебя на 1 больше, но это легко поправить, надо не mov ecx,1, а mov ecx,0, а то ещё в цикл не вошли, а уже один раз посчитали.
Сразу после выхода из цикла lp1 ecx у меня равно 46340. А чему в Паскале равно n после выхода из цикла?
0
DeemaS
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
21.06.2012, 10:17  [ТС] 3
Так это смотря какие значения брать. Вот скрин, верхнее окошко это паскаль, нижнее ассемблер. Видишь какая разница в результате суммы членов прогрессии, при равных значениях? Вот это и надо исправить
0
Миниатюры
Ошибка в результатах при подсчете суммы n-1 членов прогрессии  
skaa
Хочу в Исландию
1035 / 834 / 119
Регистрация: 10.11.2010
Сообщений: 1,629
21.06.2012, 16:34 4
Я забыл написать какие числа брал. По-моему a1=5, d=2. Это на работе, а я сегодня отгул взял.
Вижу два окна - чёрное и белое. Какое из них Паскаль выдаёт, а какое ассемблер? Завтра буду на работе - посмотрю.
0
DeemaS
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
21.06.2012, 16:40  [ТС] 5
skaa, Верхнее паскаль, нижнее ассемблер.
0
skaa
Хочу в Исландию
1035 / 834 / 119
Регистрация: 10.11.2010
Сообщений: 1,629
22.06.2012, 17:34 6
Во время второго шага первого цикла уже происходит переполнение:
1111111111+2222222222=3333333333 - в этом числе уже старший бит =1, т.е. число отрицательное, а второй цикл у тебя проходит два раза, хотя должен по логике пройти один раз. После 49 строки поставь ещё один dec ecx, и всё будет правильно.
0
DeemaS
0 / 0 / 0
Регистрация: 20.05.2012
Сообщений: 4
22.06.2012, 18:55  [ТС] 7
skaa, а может вот так: после 49й строки sub ebx,eax ? т.к. цикл заного начинается, а переполнение так и остается, т.е. нужно вернуть прежнее значение, иначе оно суммируется и получается неверный результат. как ты думаешь?
0
skaa
Хочу в Исландию
1035 / 834 / 119
Регистрация: 10.11.2010
Сообщений: 1,629
25.06.2012, 17:18 8
Скорее всего можно и так... Проверь.
0
25.06.2012, 17:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.06.2012, 17:18

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

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

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru