Modulo och python

Här diskuteras programmering och utveckling
Användarvisningsbild
Niklas Bolmdahl
Inlägg: 343
Blev medlem: 07 jun 2006, 15:46
OS: Ubuntu
Utgåva: 12.04 Precise Pangolin LTS
Ort: Lund
Kontakt:

Modulo och python

Inlägg av Niklas Bolmdahl »

Eller, ja ... matte och python antar jag att det borde stå egentligen.

Håller på o leker lite med Python (som det heter när en idiot sitter med en bok o försöker prata franska)
och jag fattar verkligen inte hur Python "tänker". Eller, jo, men inte varför.

Om jag startar den interaktiva prompten och skriver följande:

Kod: Markera allt

>>>4/(-3)
-2
>>>4%(-3)
-2
>>>4/3
1
>>>4%3
1
... så blir jag inte riktigt glad.

Samma resultat blir det av

Kod: Markera allt

>>>-4/3
-2
Men inte av

Kod: Markera allt

>>>-(4/3)
-1
Jag fattar att avrundingen väljer det minst positiva värdet när den avrundat till närmaste heltal, men den borde gå mot noll istället.
Vad är det jag inte fattar?
Senast redigerad av 1 Niklas Bolmdahl, redigerad totalt 12 gånger.
Errare humanum est
Homines quod volunt credunt
Användarvisningsbild
gasol
Inlägg: 405
Blev medlem: 27 jul 2007, 14:57
Kontakt:

SV: Modulo och python

Inlägg av gasol »

Python avrundar neråt vid heltalsdivision...


4/3 ~ 1.3333333333333333 eller 1 + (1/3)


floor(1.3333333) = 1
floor(-1.3333333) = -2


-(4/3) ger bara -(1) där 1 är resultatet av 4/3

4.0 / 3.0 kommer att producera rätt resultat.
The Black Mountain Scorpion Hoedown Bluegrass Experience Gang
From Left to Right: Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle.
Användarvisningsbild
Niklas Bolmdahl
Inlägg: 343
Blev medlem: 07 jun 2006, 15:46
OS: Ubuntu
Utgåva: 12.04 Precise Pangolin LTS
Ort: Lund
Kontakt:

SV: Modulo och python

Inlägg av Niklas Bolmdahl »

gasol skrev: Python avrundar neråt vid heltalsdivision...

4/3 ~ 1.3333333333333333 eller 1 + (1/3)

floor(1.3333333) = 1
floor(-1.3333333) = -2

-(4/3) ger bara -(1) där 1 är resultatet av 4/3
Jo, det där fattade jag redan. Min fråga var ju snarare varför.
Poängen är ju att inom ramarna för de olika datatyperna, så borde matten i språket ändå vara rimligt lik riktig matte, och en avrundning neråt borde snarast gå mot noll. Vad jag undrar över är varför det inte funkar så.
Floor-funtionen, är det en riktig funktion eller något du skrev i ett försökt att förtydliga? (hittar den inte, vad måste jag importera i så fall?)
Skulle gärna vilja se vad den gör i detalj om det är en faktisk funktion.
Errare humanum est
Homines quod volunt credunt
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

SV: Modulo och python

Inlägg av Konservburk »

dacovale skrev: Floor-funtionen, är det en riktig funktion eller något du skrev i ett försökt att förtydliga? (hittar den inte, vad måste jag importera i så fall?)
Skulle gärna vilja se vad den gör i detalj om det är en faktisk funktion.
Floor-funktionen är en "riktig" funktion: http://mathworld.wolfram.com/FloorFunction.html
Användarvisningsbild
gasol
Inlägg: 405
Blev medlem: 27 jul 2007, 14:57
Kontakt:

SV: Modulo och python

Inlägg av gasol »

dacovale skrev:
gasol skrev: Python avrundar neråt vid heltalsdivision...

4/3 ~ 1.3333333333333333 eller 1 + (1/3)

floor(1.3333333) = 1
floor(-1.3333333) = -2

-(4/3) ger bara -(1) där 1 är resultatet av 4/3
Jo, det där fattade jag redan. Min fråga var ju snarare varför.
Poängen är ju att inom ramarna för de olika datatyperna, så borde matten i språket ändå vara rimligt lik riktig matte, och en avrundning neråt borde snarast gå mot noll. Vad jag undrar över är varför det inte funkar så.
Floor-funtionen, är det en riktig funktion eller något du skrev i ett försökt att förtydliga? (hittar den inte, vad måste jag importera i så fall?)
Skulle gärna vilja se vad den gör i detalj om det är en faktisk funktion.
Skulle förmodligen tro att det är ett arv från C.
Flyttalsoperationer tar 1000000 gånger så mycket mer tid att exekuvera för tid dator and vad heltalsoperationer, speciellt division.

Heltal och flyttal lagras på två vitt skiljda sätt i din dator. (http://en.wikipedia.org/wiki/IEEE_float ... t_standard)

Jämnför ALU (Arithmetic logic unit)  http://en.wikipedia.org/wiki/Arithmetic_logic_unit
med FPU (Floating point unit)  http://en.wikipedia.org/wiki/Floating_point_unit

Jag har ingen aning om floor finns i python eller inte, men en enkelt implementation av floor skulle vara detta:
(int)(x)
dvs konvertera till en int, konverteringen till en int sker med avkapning, inte avrundning. hur man nu skriver det som en funktion i python är dock ett mysterium.
The Black Mountain Scorpion Hoedown Bluegrass Experience Gang
From Left to Right: Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle.
Lars
Inlägg: 6191
Blev medlem: 14 jan 2007, 19:31
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Ort: Stockholm

SV: Modulo och python

Inlägg av Lars »

dacovale skrev: Poängen är ju att inom ramarna för de olika datatyperna, så borde matten i språket ändå vara rimligt lik riktig matte, och en avrundning neråt borde snarast gå mot noll.
Det jag tror att du menar brukar kallas trunkering, d.v.s. att man bara hugger av decimalerna.

Funktionen floor() finns i modulen math.
Användarvisningsbild
Niklas Bolmdahl
Inlägg: 343
Blev medlem: 07 jun 2006, 15:46
OS: Ubuntu
Utgåva: 12.04 Precise Pangolin LTS
Ort: Lund
Kontakt:

SV: Modulo och python

Inlägg av Niklas Bolmdahl »

men om konvertering till int sker med trunkering / avkapning, så borde ju -4/3 bli -1, eftersom -4.0/3 blir -1.3333....
det är ju just det jag inte fattar, hur en trunkering av -1.3333.... kan bli -2
Errare humanum est
Homines quod volunt credunt
Användarvisningsbild
gasol
Inlägg: 405
Blev medlem: 27 jul 2007, 14:57
Kontakt:

SV: Modulo och python

Inlägg av gasol »

Kod: Markera allt

#include <stdio.h>

int main(int argc, char **argv) {

   printf("%d %d\n", 4/3, 4/(-3));
   return 0;
}
Skriver ut 1 -1, du har rätt i att det inte är någon trunkering som sker, utan att floor anropas i Python, kodar inte i python men som sagt en avkapning hade inte brytt sig om tecknet

Googlade lite på det hela och hittade detta:
The most controversial change in Python 2.2 heralds the start of an effort to fix an old design flaw that's been in Python from the beginning. Currently Python's division operator, /, behaves like C's division operator when presented with two integer arguments: it returns an integer result that's truncated down when there would be a fractional part. For example, 3/2 is 1, not 1.5, and (-1)/2 is -1, not -0.5. This means that the results of divison can vary unexpectedly depending on the type of the two operands and because Python is dynamically typed, it can be difficult to determine the possible types of the operands.

(The controversy is over whether this is really a design flaw, and whether it's worth breaking existing code to fix this. It's caused endless discussions on python-dev, and in July 2001 erupted into an storm of acidly sarcastic postings on comp.lang.python. I won't argue for either side here and will stick to describing what's implemented in 2.2. Read PEP 238 for a summary of arguments and counter-arguments.)
Lite mer från sidan: http://www.python.org/doc/2.2.3/whatsnew/node7.html
The Black Mountain Scorpion Hoedown Bluegrass Experience Gang
From Left to Right: Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle, Wizard on Bicycle.
Lars
Inlägg: 6191
Blev medlem: 14 jan 2007, 19:31
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Ort: Stockholm

SV: Modulo och python

Inlägg av Lars »

Grejen är att det finns en mängd olika sätt att avrunda på. Ibland är det viktigt att man använder exakt rätt metod, ibland spelar det kanske inte så stor roll. Hur som helst är det bra att känna till de olika metoderna:
  • Avrunding uppåt: går mot ∞, funktionen math.ceil()
  • Avrunding neråt: går mot -∞, funktionen math.floor()
  • Trunkering: går mot 0, funktionen int()
  • Avrundning till närmsta heltal: funktionen round()
Division mellan heltal innebär avrundning neråt. Som gasol nämnde så har det här diskuterats ganska mycket och från och med Python 3.0 kommer divisionsoperatorn alltid att returnera ett flyttal. Man kan få det så redan nu genom att använda "from __future__ import division". Dessutom finns operatorn // som kommer att fortsätta fungera precis som / gör nu, även i Python 3.0.
Användarvisningsbild
Niklas Bolmdahl
Inlägg: 343
Blev medlem: 07 jun 2006, 15:46
OS: Ubuntu
Utgåva: 12.04 Precise Pangolin LTS
Ort: Lund
Kontakt:

SV: Modulo och python

Inlägg av Niklas Bolmdahl »

Ok, så då får jag helt enkelt vara noggrann med att specifiera vad det är jag vill ha. I det här fallet vill jag ju ha trunkering, så då får jag väl helt enkelt specifiera med int(4/(-3)), eller kanske då snarare int(4//(-3)). Om jag fattat rätt så kommer 3.0 vara här om ungefär ett år. Kanske lika bra att börja lära sig koda enligt 3.0 på en gång.

Är väl egentligen inte mycket mer än att vänja sig vid att det är floor som anropas istället för att resultatet trunkeras. Skulle bara vilja ha vetat varför. (Om de hade behövt skådespelare till en ny Ronja Rövardotter-film, skulle jag söka till o bli en sån där "Vaffö' då då"-minipyssling)
Errare humanum est
Homines quod volunt credunt
Användarvisningsbild
Niklas Bolmdahl
Inlägg: 343
Blev medlem: 07 jun 2006, 15:46
OS: Ubuntu
Utgåva: 12.04 Precise Pangolin LTS
Ort: Lund
Kontakt:

SV: Modulo och python

Inlägg av Niklas Bolmdahl »

Kod: Markera allt

>>> int(4//(-3))
-2
>>> round(4//(-3))
-2.0
>>> int(4/(-3))
-2
>>> round(4/(-3))
-2.0
>>> int(4/3)
1
>>> round(4/3)
1.0 
>>> 9/5.0
1.8
>>> round(9/5)
1.0
tyvärr. Sitter hemma hos en kompis, så var tvungen att dra ner o installera python (winXP...)
round verkar ju nästan roligast av allt. som jag fattar round, så tar round det redan färdig-uträknade, floorade värdet, och gör det till ett flyttal.
EDIT2: round fungerar som Lars säger, men om man skickar en heltals-division så skickar man ju inte divisionen i sig, utan enbart det färdiguträknade värdet.


finns det nåt sätt att undvika floor och istället få en trunkering?

EDIT: ja.

Kod: Markera allt

>>> tal1 = float(raw_input("Skriv ett tal: "))
Skriv ett tal: -4
>>> tal2 = float(raw_input("Skriv ett till tal: "))
Skriv ett till tal: 3
>>> trunkerad = int(tal1/tal2)
>>> print trunkerad
-1
men det känns bakvänt att vara tvungen att använda flyttal för att få trunkering.
får nog dock betrakta mitt problem med att tvinga trunkering som löst.
Senast redigerad av 1 Niklas Bolmdahl, redigerad totalt 13 gånger.
Errare humanum est
Homines quod volunt credunt
Skriv svar

Återgå till "Programmering och webbdesign"