Problème de multiplication

Résolu/Fermé
programme - 5 avril 2018 à 16:55
Pinzou76 Messages postés 609 Date d'inscription dimanche 17 septembre 2017 Statut Membre Dernière intervention 25 février 2019 - 6 avril 2018 à 09:18
Bonjour,

J'ai actuellement un problème avec ce code
set /a hello=122500*19950
echo %hello%
(ceci est un exemple)
Ceci me retourne "-1851092296" et non "2443875000" ce qui pose un sérieux problème dans mon programme de calcul pour le traçage d'une ellipse qui foire totalement (quand a est au dessus de 300 et b de 127) je mets toujours le code au cas où cela aiderait à l'aide
@echo off
if defined __ goto hello
set __=.
call %0 %* | darkbox
set __=
pause>NUL
goto :eof
:hello
pixelFNT.exe 1
title Draw ellipse Bresenham
mode con cols=1000 lines=1000
REM Sets de base
REM Max 300 127
call:draw_ellipse 500 200 e 0 0
pause>nul
:draw_ellipse
set a=%~1
set b=%~2
set x_pos=%~4
set y_pos=%~5
if %~3 EQU c (
set /a x_pos-=%a%
set /a y_pos-=%b%
)
REM Sets pour calculs
set /a a_carre=%a%*%a%
set /a b_carre=%b%*%b%
set /a a_b=%a%*%b%
set /a dix_b=10*%b%
set /a dix_a=10*%a%
set x=0
set y=%b%
set /a dix_b_carre=%dix_b%*%dix_b%
set /a a_carre_cent_b=%a_carre%*100*%b%
set /a dix_a_carre=%dix_a%*%dix_a%
set /a dix_a_carre_divise_quatre=%dix_a_carre%/4
set /a d_un=%dix_b_carre%-%a_carre_cent_b%+%dix_a_carre_divise_quatre%
REM 1ere phase
:loop_1
set /a x_quatrieme_quadrant=%x%+%a%
set /a y_quatrieme_quadrant=%y%+%b%
set x_premier_quadrant=%x_quatrieme_quadrant%
set /a y_premier_quadrant=%y_quatrieme_quadrant%-(2*%y%)
set /a x_troisieme_quadrant=%x_quatrieme_quadrant%-(2*%x%)
set y_troisieme_quadrant=%y_quatrieme_quadrant%
set x_deuxieme_quadrant=%x_troisieme_quadrant%
set /a y_deuxieme_quadrant=%y_troisieme_quadrant%-(2*%y%)
set /a x_premier_quadrant+=%x_pos%
set /a y_premier_quadrant+=%y_pos%
set /a x_deuxieme_quadrant+=%x_pos%
set /a y_deuxieme_quadrant+=%y_pos%
set /a x_troisieme_quadrant+=%x_pos%
set /a y_troisieme_quadrant+=%y_pos%
set /a x_quatrieme_quadrant+=%x_pos%
set /a y_quatrieme_quadrant+=%y_pos%
echo /g %x_premier_quadrant% %y_premier_quadrant% /a 219 /g %x_deuxieme_quadrant% %y_deuxieme_quadrant% /a 219 /g %x_troisieme_quadrant% %y_troisieme_quadrant% /a 219 /g %x_quatrieme_quadrant% %y_quatrieme_quadrant% /a 219
set /a cent_y=100*%y%
set /a cent_x=100*%x%
set /a cent_y_moins_cinqante=%cent_y%-50
set /a cent_x_plus_cent=%cent_x%+100
set /a a_carre_cent_y_moins_cinqante=%a_carre%*%cent_y_moins_cinqante%
set /a b_carre_cent_x_plus_cent=%b_carre%*%cent_x_plus_cent%
echo %y% %cent_y% %cent_y_moins_cinqante% %a_carre% %a_carre_cent_y_moins_cinqante%> hello.txt
echo %x% %cent_x% %cent_x_plus_cent% %b_carre% %b_carre_cent_x_plus_cent%>> hello.txt
if %a_carre_cent_y_moins_cinqante% LEQ %b_carre_cent_x_plus_cent% goto 2iemephase
set /a deux_cent_x=200*%x%
set /a deux_cent_x_plus_trois_cent=%deux_cent_x%+300
set /a b_carre_deux_cent_x_plus_trois_cent=%b_carre%*%deux_cent_x_plus_trois_cent%
set /a deux_cent_y=200*%y%
set /a deux_cent_y_plus_deux_cent=%deux_cent_y%-200
set /a a_carre_deux_cent_y_plus_deux_cent=%a_carre%*%deux_cent_y_plus_deux_cent%
if %d_un% GEQ 0 goto calcul_1
set /a d_un+=%b_carre_deux_cent_x_plus_trois_cent%
set /a x+=1
goto loop_1
REM 2ieme phase
:2iemephase
set /a dix_x=10*%x%
set /a dix_x_plus_cinq=%dix_x%+5
set /a dix_x_plus_cinq_carre=%dix_x_plus_cinq%*%dix_x_plus_cinq%
set /a b_carre_dix_x_plus_cinq_carre=%b_carre%*%dix_x_plus_cinq_carre%
set /a dix_y=10*%y%
set /a dix_y_moins_dix=%dix_y%-10
set /a dix_y_moins_dix_carre=%dix_y_moins_dix%*%dix_y_moins_dix%
set /a a_carre_dix_y_moins_dix_carre=%a_carre%*%dix_y_moins_dix_carre%
set /a dix_a_carre_b_carre=%dix_a_carre%*%b_carre%
set /a d_deux=%b_carre_dix_x_plus_cinq_carre%+%a_carre_dix_y_moins_dix_carre%-%dix_a_carre_b_carre%
:loop_2
set /a x_quatrieme_quadrant=%x%+%a%
set /a y_quatrieme_quadrant=%y%+%b%
set x_premier_quadrant=%x_quatrieme_quadrant%
set /a y_premier_quadrant=%y_quatrieme_quadrant%-(2*%y%)
set /a x_troisieme_quadrant=%x_quatrieme_quadrant%-(2*%x%)
set y_troisieme_quadrant=%y_quatrieme_quadrant%
set x_deuxieme_quadrant=%x_troisieme_quadrant%
set /a y_deuxieme_quadrant=%y_troisieme_quadrant%-(2*%y%)
set /a x_premier_quadrant+=%x_pos%
set /a y_premier_quadrant+=%y_pos%
set /a x_deuxieme_quadrant+=%x_pos%
set /a y_deuxieme_quadrant+=%y_pos%
set /a x_troisieme_quadrant+=%x_pos%
set /a y_troisieme_quadrant+=%y_pos%
set /a x_quatrieme_quadrant+=%x_pos%
set /a y_quatrieme_quadrant+=%y_pos%
echo /g %x_premier_quadrant% %y_premier_quadrant% /a 219 /g %x_deuxieme_quadrant% %y_deuxieme_quadrant% /a 219 /g %x_troisieme_quadrant% %y_troisieme_quadrant% /a 219 /g %x_quatrieme_quadrant% %y_quatrieme_quadrant% /a 219
if %y% EQU 0 goto:eof
set /a deux_cent_y=200*%y%
set /a deux_cent_y_plus_trois_cent=%deux_cent_y%-300
set /a a_carre_deux_cent_y_plus_trois_cent=%a_carre%*%deux_cent_y_plus_trois_cent%
if %d_deux% LSS 0 goto calcul_2
set /a d_deux-=%a_carre%*%deux_cent_y_plus_trois_cent%
set /a y-=1
goto loop_2
:calcul_1
set /a d_un=%d_un%+%b_carre_deux_cent_x_plus_trois_cent%-%a_carre_deux_cent_y_plus_deux_cent%
set /a x+=1
set /a y-=1
goto loop_1
:calcul_2
set /a deux_cent_x=200*%x%
set /a deux_cent_x_plus_deux_cent=%deux_cent_x%+200
set /a b_carre_deux_cent_x_plus_deux_cent=%b_carre%*%deux_cent_x_plus_deux_cent%
set /a d_deux=%d_deux%+%b_carre_deux_cent_x_plus_deux_cent%-%a_carre_deux_cent_y_plus_trois_cent%
set /a x+=1
set /a y-=1
goto loop_2

(j'utilise pixelfnt.exe et darkbox.exe pour l'affichage)

Merci d'avance,

Programme

1 réponse

Pinzou76 Messages postés 609 Date d'inscription dimanche 17 septembre 2017 Statut Membre Dernière intervention 25 février 2019 190
5 avril 2018 à 17:03
Bonjour,
Je ne connais pas ce langage, mais le résultat obtenu me fait penser à un dépassement de capacité (stack overflow).
Cela se produit quand la valeur excède la limite maximale du type.

Par exemple, la valeur maximale pour un int codé sur 32 bits est 2,147,483,647.
Ici, le résultat est 2,443,875,000 donc il dépasse cette valeur.

Quel type de variable utilisez-vous pour stocker ces nombres ?
Le type du résultat est-il suffisant pour stocker un nombre aussi grand ?
Cordialement
1
En batch, une variable peut être utilisée afin de stoquer autant un nombre que du texte. En effet c'est surement cela auriez vous une solution?
0
Pinzou76 Messages postés 609 Date d'inscription dimanche 17 septembre 2017 Statut Membre Dernière intervention 25 février 2019 190
5 avril 2018 à 17:50
https://stackoverflow.com/questions/11546020/can-batch-files-not-process-large-numbers

Cette personne a les mêmes problèmes que vous et on lui répond qu'en batch ça n'est pas possible à cause du fait que cmd.exe soit une application 32bits... (a vérifier)
0
Pinzou76 Messages postés 609 Date d'inscription dimanche 17 septembre 2017 Statut Membre Dernière intervention 25 février 2019 190
5 avril 2018 à 17:52
Une possible solution ici mais elle a l'air assez complexe:

https://superuser.com/questions/827044/batch-script-32-bit-limitation-of-integer
0
programme > Pinzou76 Messages postés 609 Date d'inscription dimanche 17 septembre 2017 Statut Membre Dernière intervention 25 février 2019
5 avril 2018 à 21:47
Merci pour vos réponses ! J'ai résolu mon problème grace à la votre via ceci http://www.robvanderwoude.com/files/multiply_3rdparty_bat.txt

J'ai modifié le code pour qu'il ne soit pas si visuellement agressif et qu'on puisse l'exécuté plusieurs fois à la suite (car des variables nécessitaient d'être resettées)
@echo OFF
setlocal enableextensions
setlocal enabledelayedexpansion
call:multiplication 122500 19950
echo %resultat%
call:multiplication 5203216584 165503216
echo %resultat%
pause>nul
:multiplication

set num1cnt=
set num2cnt=
set resultat=
set tmp=
set cnt=
set colcnt=
set num1=%1
set num2=%2
for /l %%a in (1,1,2) do (
for /l %%b in (0,1,9) do (
set num%%a=!num%%a:%%b=%%b !
)
)
for %%a in (!num1!) do set /a num1cnt+=1 & set _!num1cnt!num1=%%a
for %%a in (!num2!) do set /a num2cnt+=1 & set _!num2cnt!num2=%%a
if !num1cnt! EQU 1 if !num2cnt! EQU 1 (
set /a resultat=!num1! * !num2!
goto:eof
)
for /l %%b in (!num2cnt!,-1,1) do (
for /l %%a in (!num1cnt!,-1,1) do (
set /a tmp=!_%%bnum2! * !_%%anum1! !plus! !co!
set co=
set plus=
if !tmp! GTR 9 set co=!tmp:~0,1!& set tmp=!tmp:~-1!& set plus=+
set num3_%%b=!num3_%%b!!spc!!tmp!
set spc=
set tmp=
)
if defined co set num3_%%b=!num3_%%b! !co!& set co=& set plus=
set num3_%%b=!zero!!num3_%%b!
set zero=0!spc1!!zero!
set spc1=
for %%a in (!num3_%%b!) do (
set /a cnt+=1
for %%c in (!cnt!) do set num4_%%c=!num4_%%c!%%a+
)
set cnt=
)
for /f %%a in ('set num4') do set /a colcnt+=1
for /l %%a in (1,1,!colcnt!) do set /a num5_%%a=!num4_%%a:~0,-1!
for /l %%a in (1,1,!colcnt!) do (
if defined co set /a num5_%%a=!num5_%%a! + !co!
set co=
if !num5_%%a! GTR 9 (
set co=!num5_%%a:~0,-1!
set num6=!num5_%%a:~-1!!num6!
) else (
set num6=!num5_%%a!!num6!
)
set resultat=!co!!num6!
)
goto:eof
0
Pinzou76 Messages postés 609 Date d'inscription dimanche 17 septembre 2017 Statut Membre Dernière intervention 25 février 2019 190
6 avril 2018 à 09:18
Content que ça fonctionne, n'hésitez pas à mettre le sujet en résolu :)
Bonne journée
0