<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Philben - Ms Access &#187; Numérique</title>
	<atom:link href="https://blog.developpez.com/philben/ptag/numerique/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/philben</link>
	<description></description>
	<lastBuildDate>Thu, 26 Sep 2013 19:43:53 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Un meilleur RNG&#8230;</title>
		<link>https://blog.developpez.com/philben/p10822/vba-access/un_meilleur_rng</link>
		<comments>https://blog.developpez.com/philben/p10822/vba-access/un_meilleur_rng#comments</comments>
		<pubDate>Sun, 11 Mar 2012 21:47:59 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Aléatoire]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[En parcourant le web, j&#8217;ai lu de nombreuses critiques concernant les générateurs de nombres aléatoires livrés avec les systèmes d&#8217;exploitation, les langages de programmation&#8230; Et notre couple Randomize/Rnd que vaut-il ? Tester un RNG (Random Number Generator) nécessite de lui &#8230; <a href="https://blog.developpez.com/philben/p10822/vba-access/un_meilleur_rng">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>En parcourant le web, j&rsquo;ai lu de nombreuses critiques concernant les générateurs de nombres aléatoires livrés avec les systèmes d&rsquo;exploitation, les langages de programmation&#8230;</p>
<p><strong>Et notre couple Randomize/Rnd que vaut-il ?</strong><br />
<span id="more-2"></span><br />
Tester un RNG (Random Number Generator) nécessite de lui faire passer une batterie de tests statistiques qui permettent de mesurer leur qualité.<br />
le plus célèbre jeu de tests est <em><a href="http://en.wikipedia.org/wiki/Diehard_tests">DieHards tests</a></em> de G. Marsaglia mais je me suis amusé à tester notre générateur avec le programme de <a href="http://www.fourmilab.ch/random/">fourmilab</a> (explications sur les résultats).</p>
<p><strong>Résultats</strong></p>
<blockquote><p>
Entropy = 6.960137 bits per byte.</p>
<p>Optimum compression would reduce the size<br />
of this 11469916 byte file by 12 percent.</p>
<p>Chi square distribution for 11469916 samples is 91767249.86, and randomly<br />
would exceed this value less than 0.01 percent of the times.</p>
<p>Arithmetic mean value of data bytes is 111.6449 (127.5 = random).<br />
Monte Carlo value for Pi is 3.304316894 (error 5.18 percent).<br />
Serial correlation coefficient is -0.036392 (totally uncorrelated = 0.0).
</p></blockquote>
<p>Les résultats démontrent que notre RNG n&rsquo;est pas à la hauteur de nos espérances&#8230;</p>
<p>Si vous avez besoin d&rsquo;un bon générateur de nombres aléatoires, vous avez deux possibilités :</p>
<p><strong>Récupérer un code VBA existant sur le web</strong><br />
Depuis la fin des années 90, il existe d&rsquo;excellents algorithmes qui utilisent nativement des variables &lsquo;unsigned long&rsquo; voir des &lsquo;unsigned long long&rsquo; ce qui ne facilite pas le portage en VBA avec notre type &lsquo;long&rsquo;&#8230;</p>
<p>J&rsquo;ai quand même péché sur le web deux RNG de qualité.</p>
<ul>
<li>Le fameux &lsquo;Mersenne twister&rsquo; porté <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONS/BASIC/mt19937arVBcode.txt">ici</a> en VBA.</li>
<li>et <a href="http://burtleburtle.net/bob/rand/isaacafa.html">ISAAC</a> de qualité cryptographique</li>
</ul>
<p>Ces deux RNG codés en VBA passent sans problème les tests qualité de Fourmilab.</p>
<p>Exemple avec ISAAC :</p>
<blockquote><p>
Entropy = 7.999985 bits per byte.</p>
<p>Optimum compression would reduce the size<br />
of this 11469916 byte file by 0 percent.</p>
<p>Chi square distribution for 11469916 samples is 236.35, and randomly<br />
would exceed this value 79.31 percent of the times.</p>
<p>Arithmetic mean value of data bytes is 127.4950 (127.5 = random).<br />
Monte Carlo value for Pi is 3.141571792 (error 0.00 percent).<br />
Serial correlation coefficient is -0.000191 (totally uncorrelated = 0.0).
</p></blockquote>
<p><strong>En adapter un&#8230;</strong><br />
Je dis bien &lsquo;adapter&rsquo; et non &lsquo;programmer&rsquo; car se sont des algorithmes très pointus.<br />
Je me suis d&rsquo;abord penché sur des sources qui utilisaient des variables &lsquo;uint32&prime; dans le but de simplifier l&rsquo;adaptation.<br />
Leur qualité dépassait rarement celle de notre Rnd et j&rsquo;ai du me résoudre à explorer les sources &lsquo;modernes&rsquo; qui exploitent les &lsquo;uint64&prime;.<br />
Je me suis intéressé à la <a href="http://school.anhb.uwa.edu.au/personalpages/kwessen/shared/Marsaglia03.html">méthode MWC</a> &lsquo;Multiply with carry&rsquo; de G. Marsaglia tout particulièrement à l&rsquo;algorithme MWC256.</p>
<p>Voici donc mon adaptation de son code :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Random number generator - MWC256 - Multiply with Carry<br />
</span><span style="color: #008000;">'Author : George Marsaglia<br />
</span><span style="color: #008000;">' Reference : http://school.anhb.uwa.edu.au/personalpages/kwessen/shared/Marsaglia03.html<br />
</span><span style="color: #008000;">' Period about 2^8222. Uses a static array Q[256] and an initial carry 'c',<br />
</span><span style="color: #008000;">' the Q array filled with 256 random 32-bit integers in the calling program<br />
</span><span style="color: #008000;">' and an initial carry c&lt;809430660 for the multiply-with-carry operation<br />
</span><span style="color: #008000;">'Adapted from C to VBA : Philben - v1.0 - 03/2012<br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> MWC256_UINT32(<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Start <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">False</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span><br />
&nbsp; &nbsp;Const ULL <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 2 ^ 64<br />
&nbsp; &nbsp;Const UL <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 2 ^ 32<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Static</span> Q(1 <span style="color: #8D38C9; font-weight: bold;">To</span> 256) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>, c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>, a <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> t <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>, v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> Start <span style="color: #8D38C9; font-weight: bold;">Or</span> i = 0 <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; Randomize<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">'c &lt; 809430660 - 0 &lt;= Rnd &lt; 1 - Marsaglia : c=362436<br />
</span> &nbsp; &nbsp; &nbsp;c = CDec(CLng((809430660 - 2 ^ 12) * Rnd() + 2 ^ 11))<br />
&nbsp; &nbsp; &nbsp; a = CDec(809430660)<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> 256<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Q(i) = CLng(Rnd() * (2 ^ 31 - 1))<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #008000;">'warm up<br />
</span> &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MWC256_UINT32<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Loop</span> <span style="color: #8D38C9; font-weight: bold;">Until</span> i = 256<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
<br />
&nbsp; &nbsp;i = i + 1<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> i &gt; 256 <span style="color: #8D38C9; font-weight: bold;">Then</span> i = 1<br />
<br />
&nbsp; &nbsp;v = a * Q(i) + c<br />
&nbsp; &nbsp;t = CDec(v - Int(v / ULL) * ULL)<br />
&nbsp; &nbsp;c = CDec(Int(t / UL))<br />
&nbsp; &nbsp;Q(i) = v - Int(v / UL) * UL<br />
<br />
&nbsp; &nbsp;MWC256_UINT32 = Q(i)<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span><br />
<br />
<span style="color: #008000;">'Signed integer : (-2^31 to 2^31-1) ?<br />
</span><span style="color: #008000;">'author : philben<br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> MWC256_INT32(<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Start <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">False</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span><br />
&nbsp; &nbsp;MWC256_INT32 = CLng(MWC256_UINT32(Start) - &amp;H7FFFFFFF)<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span><br />
<br />
<span style="color: #008000;">'Double : (0.0, 1.0) ?<br />
</span><span style="color: #008000;">'author : philben - v1.01<br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> MWC256_Dbl(<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Start <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">False</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span><br />
&nbsp; &nbsp;MWC256_Dbl = MWC256_UINT32(Start) * 2.32830643653869E-10<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>et le résultat des tests :</p>
<blockquote><p>
Entropy = 7.999985 bits per byte.</p>
<p>Optimum compression would reduce the size<br />
of this 11469916 byte file by 0 percent.</p>
<p>Chi square distribution for 11469916 samples is 245.85, and randomly<br />
would exceed this value 64.83 percent of the times.</p>
<p>Arithmetic mean value of data bytes is 127.4586 (127.5 = random).<br />
Monte Carlo value for Pi is 3.144400759 (error 0.09 percent).<br />
Serial correlation coefficient is -0.000303 (totally uncorrelated = 0.0).
</p></blockquote>
<p>Il semble que cette adaptation fonctionne bien et à l&rsquo;avantage d&rsquo;être plus rapide que les deux précédentes mais beaucoup plus lente que son équivalent en C et que Rnd&#8230;<br />
Pour avoir un ordre d&rsquo;idée, compter moins de 2 secondes par million de nombres générés.</p>
<p>Un autre inconvénient de mon portage est qu&rsquo;il n&rsquo;est validé que par moi (!) et je ne suis pas particulièrement fier de l&rsquo;initialisation de l&rsquo;algorithme&#8230;</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fonctions Min / Max d&#8217;une série de valeurs</title>
		<link>https://blog.developpez.com/philben/p10821/vba-access/fonctions_min_max_d_une_serie_de_valeurs</link>
		<comments>https://blog.developpez.com/philben/p10821/vba-access/fonctions_min_max_d_une_serie_de_valeurs#comments</comments>
		<pubDate>Sun, 11 Mar 2012 20:57:10 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Chaîne de caractères]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Date]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Deux petites fonctions qui permettent d&#8217;extraire la valeur minimale ou maximale d&#8217;une série de valeurs dans une requête SQL ou dans un code VBA. Les fonctions Public Function getMin(ParamArray pa() As Variant) As Variant &#160; &#160;Dim v As Variant &#160; &#8230; <a href="https://blog.developpez.com/philben/p10821/vba-access/fonctions_min_max_d_une_serie_de_valeurs">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Deux petites fonctions qui permettent d&rsquo;extraire la valeur minimale ou maximale d&rsquo;une série de valeurs dans une requête SQL ou dans un code VBA.<br />
<span id="more-1"></span><br />
<strong>Les fonctions</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> getMin(<span style="color: #151B8D; font-weight: bold;">ParamArray</span> pa() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> <span style="color: #8D38C9; font-weight: bold;">Each</span> v <span style="color: #8D38C9; font-weight: bold;">In</span> pa<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> getMin &gt; v <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMin = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">ElseIf</span> IsEmpty(getMin) <span style="color: #8D38C9; font-weight: bold;">And</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> IsNull(v) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMin = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> v<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span><br />
<br />
<span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> getMax(<span style="color: #151B8D; font-weight: bold;">ParamArray</span> pa() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> <span style="color: #8D38C9; font-weight: bold;">Each</span> v <span style="color: #8D38C9; font-weight: bold;">In</span> pa<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> getMax &lt; v <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMax = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">ElseIf</span> IsEmpty(getMax) <span style="color: #8D38C9; font-weight: bold;">And</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> IsNull(v) <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getMax = v<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> v<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Paramètre</strong><br />
Elles acceptent un nombre quelconque de valeurs en paramètre grâce à l&rsquo;utilisation du type ParamArray.</p>
<p><strong>Particularités</strong></p>
<ul>
<li>Ces fonctions gèrent les NULL c&rsquo;est à dire qu&rsquo;elles ne renvoient un NULL que si toutes les valeurs passées en paramètre sont nulles.</li>
<li>Le type des paramètres doit être uniforme et peut être numérique, date ou string. Une adaptation du code sera nécessaire pour une bonne gestion des accents et autres caractères particuliers.</li>
</ul>
<p><strong>Exemples</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Pas d'erreur si aucun paramètre... <br />
</span>? getMax(), getMin() <br />
<br />
<span style="color: #008000;">'Renvoient 0 : &nbsp;<br />
</span>? getMax(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, <span style="color: #00C2FF; font-weight: bold;">NULL</span>), getMin(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, <span style="color: #00C2FF; font-weight: bold;">NULL</span>) <br />
<br />
<span style="color: #008000;">'Renvoient 5 et -1 <br />
</span>? getMax(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, 5, -1, <span style="color: #00C2FF; font-weight: bold;">NULL</span>), getMin(<span style="color: #00C2FF; font-weight: bold;">NULL</span>, 0, 5, -1, <span style="color: #00C2FF; font-weight: bold;">NULL</span>)</div></div>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Trouver la Nième plus petite valeur d&#8217;un tableau</title>
		<link>https://blog.developpez.com/philben/p11152/vba-access/trouver_la_nieme_plus_petite_valeur_d_un</link>
		<comments>https://blog.developpez.com/philben/p11152/vba-access/trouver_la_nieme_plus_petite_valeur_d_un#comments</comments>
		<pubDate>Tue, 17 Jul 2012 00:05:14 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[On a souvent besoin de trouver la valeur mini ou maxi d&#8217;un tableau de valeurs numériques mais plus rarement la 10ème plus petite valeur, la 10 000 000ème&#8230; Je vous présente ici une implémentation en VBA d&#8217;un algorithme tout en &#8230; <a href="https://blog.developpez.com/philben/p11152/vba-access/trouver_la_nieme_plus_petite_valeur_d_un">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>On a souvent besoin de trouver la valeur mini ou maxi d&rsquo;un tableau de valeurs numériques mais plus rarement la 10ème plus petite valeur, la 10 000 000ème&#8230; Je vous présente ici une implémentation en VBA d&rsquo;un algorithme <strong>tout en un</strong>, d&rsquo;une rare simplicité qui sélectionne en une fraction de seconde la valeur du rang désiré.<br />
<span id="more-11"></span><br />
<strong>L&rsquo;algorithme</strong><br />
Cet algorithme, tout comme le célèbre quicksort, est basé sur le partitionnement du tableau de valeurs. Il est dû à <a href="http://dhost.info/zabrodskyvlada/3alg.html">Zabrodsky</a> qui améliora sensiblement un algo proposé par N. Wirth (1976). </p>
<p>Voici mon implémentation en VBA de l&rsquo;algorithme de Zabrodsky dans le cas d&rsquo;un tableau <strong>d&rsquo;entiers long</strong>:</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> KthSmallest(<span style="color: #151B8D; font-weight: bold;">ByRef</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
<span style="color: #008000;">'http://dhost.info/zabrodskyvlada/3alg.html <br />
</span><span style="color: #008000;">'implementation in VBA by Philben - v1.0 <br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, tmp <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, l <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp;<br />
&nbsp; &nbsp;l = <span style="color: #151B8D; font-weight: bold;">LBound</span>(a) <br />
&nbsp; &nbsp;r = <span style="color: #151B8D; font-weight: bold;">UBound</span>(a) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">While</span> l &lt; r <br />
&nbsp; &nbsp; &nbsp; x = a(k) <br />
&nbsp; &nbsp; &nbsp; i = l <br />
&nbsp; &nbsp; &nbsp; j = r <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Do</span> <span style="color: #8D38C9; font-weight: bold;">Until</span> j &lt; k <span style="color: #8D38C9; font-weight: bold;">Or</span> k &lt; i <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">While</span> a(i) &lt; x: i = i + 1: Wend <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">While</span> x &lt; a(j): j = j - 1: Wend <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;tmp = a(i): a(i) = a(j): a(j) = tmp <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i = i + 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = j - 1 <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Loop</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> j &lt; k <span style="color: #8D38C9; font-weight: bold;">Then</span> l = i <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> k &lt; i <span style="color: #8D38C9; font-weight: bold;">Then</span> r = j <br />
&nbsp; &nbsp;Wend <br />
&nbsp; &nbsp;KthSmallest = a(k) <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Il existe de nombreux autres algorithmes (selectSmallest in Numerical Recipes, findElementAtRank, quickSelect, &#8230;) et vous trouverez <a href="http://ndevilla.free.fr/median/median.pdf">ici</a> une publication sur le sujet.</p>
<p><strong>Paramètres de la fonction</strong><br />
Le premier paramètre est le tableau des valeurs et le deuxième (k) est le rang pour lequel on souhaite connaître la valeur associée.</p>
<p>Par exemple, le minimum d&rsquo;un tableau est recherché par k = 1 si l&rsquo;indice le plus faible du tableau est 1, et plus généralement avec k = LBound(MonTableau).<br />
Le maximum du tableau est recherché avec k = UBound(MonTableau) et la 10ème plus petite valeur avec k = 10 (si LBound(MonTableau)=1).</p>
<p><strong>Exemple</strong><br />
Soit un tableau de base 1 contenant les valeurs <strong>5, 3, 7, 1, 5</strong>.<br />
L&rsquo;algo retournera :</p>
<ul>
<li>1 pour k = 1</li>
<li>3 pour k = 2</li>
<li>5 pour k = 3 (médiane des valeurs) et k = 4</li>
<li>7 pour k = 5</li>
</ul>
<p><strong>Comment faire si mon tableau est de type Double par exemple ?</strong><br />
Il suffit de modifier certains types de variable en DOUBLE et le type retourné par la fonction :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> KthSmallest(<span style="color: #151B8D; font-weight: bold;">ByRef</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">DOUBLE</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">DOUBLE</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">DOUBLE</span>, tmp <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">DOUBLE</span><br />
...</div></div>
<p><strong>Vérification de l&rsquo;implémentation en VBA</strong><br />
La fonction suivante permet de vérifier succinctement que l&rsquo;algorithme remplit bien sa mission.<br />
Vous pouvez modifier à votre guise les constantes cMinIndice, cMaxIndice.</p>
<p>Pour l&rsquo;utiliser, copier l&rsquo;ensemble du code dans un module VBA, placer le focus dans la fonction puis appuyer sur &lsquo;<strong>F5</strong>&lsquo; pour l&rsquo;exécuter. Les résultats s&rsquo;affichent dans la fenêtre &lsquo;Exécution&rsquo; (Ctrl+G)</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> TestQualiteKth() <br />
<span style="color: #008000;">'Plus le nombre d'indices est élevé (cMaxIndice - cMinIndice + 1), plus la fonction prend du temps... <br />
</span><span style="color: #008000;">'Pour 1000 indices par exemple, elle teste alors 4000 tableaux de 1000 indices... <br />
</span><span style="color: #008000;">'Tester aussi bien un nombre d'indices pair et impair <br />
</span> &nbsp; Const cMinIndice <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 1 &nbsp; &nbsp;<span style="color: #008000;">'Indice mini du tableau (= à l'indice mini)<br />
</span> &nbsp; Const cMaxIndice <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 1000 <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, aBackup() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, n <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">ReDim</span> a(cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice) <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">ReDim</span> aBackup(cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice) <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #008000;">'Test n°1 : Tableau de valeurs croissantes <br />
</span> &nbsp; <span style="color: #008000;">'Chaque indice correspond à sa valeur (a(1)=1, a(2)=2,...) <br />
</span> &nbsp; <span style="color: #008000;">'La Nième valeur est égale au Nième indice <br />
</span> &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice: a(n) = n: <span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp; &nbsp;aBackup = a &nbsp; <span style="color: #008000;">'un tableau dynamique peut être copié comme une variable simple contrairement à un tableau statique <br />
</span> &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice <br />
&nbsp; &nbsp; &nbsp; r = KthSmallest(a, n) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> r &lt;&gt; n <span style="color: #8D38C9; font-weight: bold;">Then</span> Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Test n°1&quot;</span>, <span style="color: #800000;">&quot;Erreur pour n=&quot;</span>, n, <span style="color: #800000;">&quot;Résultat=&quot;</span>, r <br />
&nbsp; &nbsp; &nbsp; a = aBackup <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #008000;">'Test n°2 : Tableau de valeurs décroissantes <br />
</span> &nbsp; <span style="color: #008000;">'Chaque indice correspond à sa valeur opposée (a(cMinIndice)=cMaxIndice, a(cMinIndice+1)=cMaxIndice-1,...) <br />
</span> &nbsp; <span style="color: #008000;">'La Nième valeur est égale au Nième indice <br />
</span> &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice: a(n) = cMaxIndice - n + cMinIndice: <span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp; &nbsp;aBackup = a <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice <br />
&nbsp; &nbsp; &nbsp; r = KthSmallest(a, n) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> r &lt;&gt; n <span style="color: #8D38C9; font-weight: bold;">Then</span> Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Test n°2&quot;</span>, <span style="color: #800000;">&quot;Erreur pour n=&quot;</span>, n, <span style="color: #800000;">&quot;Résultat=&quot;</span>, r <br />
&nbsp; &nbsp; &nbsp; a = aBackup <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #008000;">'Test n°3 : Tableau de valeurs identiques sauf une <br />
</span> &nbsp; <span style="color: #008000;">'Toutes les valeurs sauf une (=1) sont égales à 0 <br />
</span> &nbsp; <span style="color: #008000;">'Tous les résultats sont égaux à 0 sauf pour le dernier indice (=1) <br />
</span> &nbsp; Randomize <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice: a(n) = 0: <span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp; &nbsp;aBackup = a <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice <br />
&nbsp; &nbsp; &nbsp; a(Int((cMaxIndice - cMinIndice + 1) * Rnd() + cMinIndice)) = 1 <br />
&nbsp; &nbsp; &nbsp; r = KthSmallest(a, n) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> (n &lt; cMaxIndice <span style="color: #8D38C9; font-weight: bold;">And</span> r &lt;&gt; 0) <span style="color: #8D38C9; font-weight: bold;">Or</span> (n = cMaxIndice <span style="color: #8D38C9; font-weight: bold;">And</span> r &lt;&gt; 1) <span style="color: #8D38C9; font-weight: bold;">Then</span> Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Test n°3&quot;</span>, <span style="color: #800000;">&quot;Erreur pour n =&quot;</span>, n, <span style="color: #800000;">&quot;Résultat =&quot;</span>, r <br />
&nbsp; &nbsp; &nbsp; a = aBackup <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #008000;">'Test n°4 : Tableau de valeurs identiques sauf une <br />
</span> &nbsp; <span style="color: #008000;">'Toutes les valeurs sauf une (=0) sont égales à 1 <br />
</span> &nbsp; <span style="color: #008000;">'Tous les résultats sont égaux à 1 sauf pour le premier indice (=0) <br />
</span> &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice: a(n) = 1: <span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp; &nbsp;aBackup = a <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice <br />
&nbsp; &nbsp; &nbsp; a(Int((cMaxIndice - cMinIndice + 1) * Rnd() + cMinIndice)) = 0 <br />
&nbsp; &nbsp; &nbsp; r = KthSmallest(a, n) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> (n &gt; cMinIndice <span style="color: #8D38C9; font-weight: bold;">And</span> r &lt;&gt; 1) <span style="color: #8D38C9; font-weight: bold;">Or</span> (n = cMinIndice <span style="color: #8D38C9; font-weight: bold;">And</span> r &lt;&gt; 0) <span style="color: #8D38C9; font-weight: bold;">Then</span> Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Test n°4&quot;</span>, <span style="color: #800000;">&quot;Erreur pour n =&quot;</span>, n, <span style="color: #800000;">&quot;Résultat =&quot;</span>, r <br />
&nbsp; &nbsp; &nbsp; a = aBackup <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> n <br />
&nbsp;<br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;*** fin ***&quot;</span> <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p><strong>Performance de l&rsquo;algorithme</strong><br />
La fonction suivante permet de tester la performance de l&rsquo;algorithme sur un tableau de <strong>10 000 000 de valeurs</strong> !<br />
Si vous souhaitez réduire la taille du tableau, il faut alors jouer sur la constante &lsquo;cMaxIndice&rsquo;. Pour modifier le rang de la valeur à trouver, modifier la constante &lsquo;cNiemeValeur&rsquo; qui doit être comprise obligatoirement entre 1 et &lsquo;cMaxIndice&rsquo;</p>
<p>Pour déterminer la durée de traitement de l&rsquo;algorithme, on utilise l&rsquo;API timeGetTime. Il faut donc ajouter la ligne suivante en tête du module VBA :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Option</span> <span style="color: #E56717; font-weight: bold;">Compare</span> Database <br />
<span style="color: #E56717; font-weight: bold;">Option</span> <span style="color: #E56717; font-weight: bold;">Explicit</span> <br />
&nbsp;<br />
<span style="color: #E56717; font-weight: bold;">Private</span> <span style="color: #151B8D; font-weight: bold;">Declare</span> <span style="color: #E56717; font-weight: bold;">Function</span> timeGetTime Lib <span style="color: #800000;">&quot;winmm.dll&quot;</span> () <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span></div></div>
<p>Copier l&rsquo;ensemble du code suivant dans le module VBA où l&rsquo;API est déclarée, placer le focus dans la fonction puis appuyer sur &lsquo;<strong>F5</strong>&lsquo; pour l&rsquo;exécuter. Les résultats s&rsquo;affichent dans la fenêtre &lsquo;Exécution&rsquo; (Ctrl+G)</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> TestPerformanceKth() <br />
&nbsp; &nbsp;Const cMaxIndice <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 10 ^ 7 &nbsp;<span style="color: #008000;">'Nombre maximum d'indices du tableau (10^7 = 10 000 000) <br />
</span> &nbsp; Const cMaxValeur <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 10 ^ 8 &nbsp;<span style="color: #008000;">'Valeur maxi <br />
</span> <br />
&nbsp; &nbsp;Const cNiemeValeur <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 10 ^ 3 &nbsp; <span style="color: #008000;">'Nième valeur retournée doit être comprise entre 1 &lt;= cNiemeValeur &lt;= cMaxIndice <br />
</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, t <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> s <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> <br />
&nbsp;<br />
&nbsp; &nbsp;Randomize <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">ReDim</span> a(1 <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> cMaxIndice <br />
&nbsp; &nbsp; &nbsp; a(i) = Rnd() * cMaxValeur <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp;<br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Départ...&quot;</span> <br />
&nbsp; &nbsp;t = timeGetTime <br />
&nbsp; &nbsp;r = KthSmallest(a, cNiemeValeur) <br />
&nbsp; &nbsp;<span style="color: #008000;">'r = FindMini(a) 'recherche seulement la valeur mini <br />
</span> &nbsp; t = timeGetTime - t <br />
&nbsp; &nbsp;s = Switch(cNiemeValeur = 1, <span style="color: #800000;">&quot;plus petite valeur est : &quot;</span>, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cNiemeValeur &lt; cMaxIndice, cNiemeValeur &amp; <span style="color: #800000;">&quot;ème plus petite valeur est : &quot;</span>, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #00C2FF; font-weight: bold;">True</span>, <span style="color: #800000;">&quot;plus grande valeur est : &quot;</span>) <br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> vbTab &amp; <span style="color: #800000;">&quot;La &quot;</span> &amp; s &amp; r, <span style="color: #800000;">&quot;- Temps écoulé : &quot;</span> &amp; t &amp; <span style="color: #800000;">&quot; ms&quot;</span>, vbNewLine &amp; <span style="color: #800000;">&quot;Fin&quot;</span> <br />
&nbsp;<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Avec mon système et ces paramètres, l&rsquo;algorithme retourne le résultat du 1000ème rang entre <strong>250ms et 750ms </strong> (plus ou moins de swap et de comparaisons selon les nombres aléatoires générés).</p>
<p>En paramétrant la constante &lsquo;cNiemeValeur&rsquo; à <strong>1</strong> pour obtenir la plus petite valeur du tableau, vous pouvez comparer la performance de l&rsquo;algorithme avec la fonction suivante :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> FindMini(<span style="color: #151B8D; font-weight: bold;">ByRef</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp;<br />
&nbsp; &nbsp;k = <span style="color: #151B8D; font-weight: bold;">LBound</span>(a) <br />
&nbsp; &nbsp;x = a(k) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = k + 1 <span style="color: #8D38C9; font-weight: bold;">To</span> <span style="color: #151B8D; font-weight: bold;">UBound</span>(a) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> a(i) &lt; x <span style="color: #8D38C9; font-weight: bold;">Then</span> x = a(i) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp;FindMini = x <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Comme vous pouvez le constater, les temps sont très proches dans ce cas de figure (temps en <em><strong>O</strong></em>(N)) et la recherche de la valeur maximale du tableau est tout aussi rapide&#8230;</p>
<p><strong>Points faibles de l&rsquo;algorithme</strong><br />
L&rsquo;ordre des éléments du tableau d&rsquo;origine est modifié. Si nécessaire, travailler avec une copie du tableau ou utiliser l&rsquo;algorithme <a href="http://pine.cs.yale.edu/pinewiki/QuickSelect">quickselect</a>.</p>
<p>De plus, lorsque toutes les valeurs du tableau sont identiques, le temps d&rsquo;exécution devient alors beaucoup plus long.</p>
<p> @+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Somme exacte en double précision</title>
		<link>https://blog.developpez.com/philben/p11214/vba-access/somme_exacte_en_double_precision</link>
		<comments>https://blog.developpez.com/philben/p11214/vba-access/somme_exacte_en_double_precision#comments</comments>
		<pubDate>Mon, 13 Aug 2012 09:46:48 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Certaines sommes en double précision sont entâchées d&#8217;erreurs d&#8217;arrondi (round-off error) qui peuvent fausser significativement les résultats. Je vous présente un algorithme qui compense ces erreurs. La fonction en VBA Public Function SommeExacte(ByVal s As Double, ByVal x As Double, &#8230; <a href="https://blog.developpez.com/philben/p11214/vba-access/somme_exacte_en_double_precision">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Certaines sommes en double précision sont entâchées d&rsquo;erreurs d&rsquo;arrondi (round-off error) qui peuvent fausser significativement les résultats. Je vous présente un algorithme qui compense ces erreurs.<br />
<span id="more-14"></span><br />
<strong>La fonction en VBA</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> SommeExacte(<span style="color: #151B8D; font-weight: bold;">ByVal</span> s <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, <span style="color: #151B8D; font-weight: bold;">ByRef</span> c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
<span style="color: #008000;">'Algorithme de Shewchuk / Knuth - TwoSum() <br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Dim</span> y <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, z <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp; &nbsp;y = s + x <br />
&nbsp; &nbsp;z = y - x <br />
&nbsp; &nbsp;c = c - ((z - s) + ((y - z) - x)) <br />
&nbsp; &nbsp;SommeExacte = y <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>On passe en argument à cette fonction la somme courante (s), la valeur à ajouter (x) et le troisième argument est la variable passée en référence qui contiendra la correction à appliquer après les sommes.<br />
La fonction retourne la somme non corrigée.</p>
<p><strong>Test</strong><br />
Pour tester l&rsquo;efficacité de la correction, on compare le résultat obtenu avec celui de la somme en type décimal. Pour rappel, le type decimal n&rsquo;est pas la solution universelle car la plage des nombres est limitée et sa vitesse est lente.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> TestSomme() <br />
&nbsp; &nbsp;Const cNbBoucle <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 1000000 <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, s <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp;<br />
&nbsp; &nbsp;v = CDec(0) <br />
&nbsp; &nbsp;x = 0.1 <br />
&nbsp; &nbsp;c = 0 <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> cNbBoucle <br />
&nbsp; &nbsp; &nbsp; s = SommeExacte(s, x, c) <br />
&nbsp; &nbsp; &nbsp; v = v + x <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp;Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Somme (decimal):&quot;</span> &amp; v, <span style="color: #800000;">&quot;Somme:&quot;</span> &amp; s, <span style="color: #800000;">&quot;Somme exacte:&quot;</span> &amp; (s + c) <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>La somme naïve en double précision (s = s + x) reste beaucoup plus rapide que la somme exacte qui sera donc réservée aux cas l&rsquo;exigeant.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Approximer, en double précision, la loi normale gaussienne et son inverse</title>
		<link>https://blog.developpez.com/philben/p11198/vba-access/approximer_en_double_precision_la_loi_no</link>
		<comments>https://blog.developpez.com/philben/p11198/vba-access/approximer_en_double_precision_la_loi_no#comments</comments>
		<pubDate>Sat, 04 Aug 2012 08:38:53 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Loi normale]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je vous propose deux fonctions en VBA pour Access qui estiment la loi normale (ou loi de Laplace-Gauss) et son inverse en double précision. Pour rappel, Excel propose en standard ces fonctions (NORMDIST, NORMINV, NORMSDIST, NORMSINV) et des fonctions encore &#8230; <a href="https://blog.developpez.com/philben/p11198/vba-access/approximer_en_double_precision_la_loi_no">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Je vous propose deux fonctions en VBA pour Access qui estiment la loi normale (ou loi de Laplace-Gauss) et son inverse en double précision. Pour rappel, Excel propose en standard ces fonctions (NORMDIST, NORMINV, NORMSDIST, NORMSINV) et des fonctions encore plus précises depuis Excel 2010 (NORM_DIST, NORM_INV, NORM_S_DIST, NORM_S_INV).</p>
<p><img src="http://philben.developpez.com/CourbeGauss.png" alt="Courbe de Gauss" title="Courbe de Gauss" /><br />
<span id="more-13"></span><br />
<strong>Loi normale</strong><br />
Cette fonction permet de trouver la probabilité cumulée (aire sous la courbe de la distribution gaussienne) d&rsquo;une variable aléatoire X.<br />
Pour ce faire, je me suis appuyé sur l&rsquo;un des meilleurs algorithmes (dixit G. Marsaglia) pour calculer la fonction d&rsquo;erreur complémentaire  qui permet d&rsquo;exprimer la fonction de répartition de la loi normale.<br />
Cet algorithme est dû à <a href="http://www.kurims.kyoto-u.ac.jp/~ooura/index.html"><strong>Takuya OOURA</strong> (1996)</a> que j&rsquo;ai implémenté en VBA :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> derfc(<span style="color: #151B8D; font-weight: bold;">ByVal</span> X <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
<span style="color: #008000;">'Complementary error function in double precision <br />
</span><span style="color: #008000;">'http://www.kurims.kyoto-u.ac.jp/~ooura/index.html <br />
</span><span style="color: #008000;">'Copyright(C) 1996 Takuya OOURA : You may use, copy, modify this code for any purpose and without fee. <br />
</span><span style="color: #008000;">'Implementation en VBA par Philben - v1.0 <br />
</span> &nbsp; &nbsp;<br />
&nbsp; &nbsp;Const C0 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.27109764952614E-03 + 9.2E-19, C1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.1931402283834E-04 + 9.44E-19, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 3.96385097360513E-03 + 5E-18, C3 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 8.70779635317295E-04 + 8.28E-19, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C4 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 7.73672528313526E-03 + 6.68E-18, C5 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 3.83335126264887E-03 + 3.03E-18, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C6 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.27223813782122E-02 + 7.55E-17, C7 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.013382364453346 + 6.9E-18, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C8 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.61315329733252E-02 + 2.48E-17, C9 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 3.90976845588484E-02 + 3.5E-18, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C10 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 2.49367200053503E-03 + 3.04E-18 <br />
&nbsp; &nbsp;Const C11 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 8.38864557023001E-02 + 9.92E-17, C12 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.119463959964325 + 4.15E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C13 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.66207924969367E-02 + 3.56E-17, C14 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.357524274449531 + 4.3E-17, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C15 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.80527640875291 + 5.67E-16, C16 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.18902982909273 + 3.33E-15, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C17 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.37040217682338 + 1.67E-15, C18 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.31314653831023 + 9.8E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C19 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.07925515155856 + 6.77E-15, C20 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.774368199119538 + 6.09E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C21 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.490165080585318 + 4.24E-16, C22 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.275374741597376 + 7.82E-16 <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> t <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, u <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, y <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp;<br />
&nbsp; &nbsp;t = 3.97886080735226 / (Abs(X) + 3.97886080735226) <br />
&nbsp; &nbsp;u = t - 0.5 <br />
&nbsp; &nbsp;y = (((((((((C0 * u + C1) * u - C2) * u - C3) * u + C4) * u + C5) * u - C6) * u - C7) * u + C8) * u + C9) * u + C10 <br />
&nbsp; &nbsp;y = ((((((((((((y * u - C11) * u - C12) * u + C13) * u + C14) * u + C15) * u + C16) * u + C17) * u + C18) * u + C19) * _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; u + C20) * u + C21) * u + C22) * t * Exp(-X * X) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> X &lt; 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> derfc = 2 - y <span style="color: #8D38C9; font-weight: bold;">Else</span>: derfc = y <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>La précision de la version VBA est certainement moins bonne que la version en C de Takura Ooura car il utilise des constantes avec plus de 15 chiffres significatifs. En effet, VBA n&rsquo;affiche que 15 chiffres pour le type Double bien qu&rsquo;il conserve en faite 16 chiffres en interne&#8230;<br />
Pour cette raison, chaque constante est définie comme la somme de deux nombres pour conserver ce 16ème chiffre de précision.</p>
<p>La fonction VBA pour calculer la loi normale est :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'--------------------------------------------------------------------------------------- <br />
</span><span style="color: #008000;">' Procédure &nbsp; &nbsp;: LoiNormale &nbsp; [Function] <br />
</span><span style="color: #008000;">' Auteur &nbsp; &nbsp; &nbsp; : Philben - Free to use <br />
</span><span style="color: #008000;">' Retour &nbsp; &nbsp; &nbsp; : Double <br />
</span><span style="color: #008000;">' Version &nbsp; &nbsp; &nbsp;: 2.0 <br />
</span><span style="color: #008000;">' Objet &nbsp; &nbsp; &nbsp; &nbsp;: Détermine la probabilité cumulée ou non d'une distribution normale en fonction <br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: d'une variable X, de la moyenne et de l'écart-type de la distribution <br />
</span><span style="color: #008000;">' Historique &nbsp; : v2.0 : Double précision (07/2012) <br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v1.0 : Simple précision (07/2007) <br />
</span><span style="color: #008000;">'--------------------------------------------------------------------------------------- <br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> LoiNormale(<span style="color: #151B8D; font-weight: bold;">ByVal</span> X <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Esperance <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> EcartType <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> CumulProbabilite <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">True</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> EcartType &lt;= 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; LoiNormale = -1 <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> CumulProbabilite <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;LoiNormale = derfc((Esperance - X) / (EcartType * Sqr(2))) * 0.5 <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Else</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;X = (X - Esperance) / EcartType <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;LoiNormale = Exp(-X * X * 0.5) / (EcartType * Sqr(8 * Atn(1))) <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Les paramètres sont la variable aléatoire <strong>X</strong> pour laquelle on cherche la probabilité correspondante, <strong>l&rsquo;espérance</strong> de la distribution (moyenne mu), <strong>l&rsquo;écart-type</strong> de la distribution (standard deviation in english) et <strong>&lsquo;CumulProbabilite&rsquo;</strong> un booléen à vrai (par défaut) si on souhaite obtenir la probabilité cumulée de la fonction de répartition.<br />
Par défaut, l&rsquo;espérance est 0 et l&rsquo;écart-type à 1 ce qui correspond aux paramètres la loi normale centrée réduite (ou standard) N(0,1) d&rsquo;espérance égale à 0 et de variance égale à 1.</p>
<p><strong>Loi normale inverse</strong><br />
Cette fonction permet de trouver la variable aléatoire X associée à une probabilité cumulée. Ooura propose aussi un algorithme qui calcul l&rsquo;inverse de la fonction d&rsquo;erreur complémentaire qui permet d&rsquo;obtenir des résultats meilleurs qu&rsquo;une recherche par bisection avec la fonction derfc.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> dierfc(<span style="color: #151B8D; font-weight: bold;">ByVal</span> y <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
<span style="color: #008000;">'Inverse of complementary error function in double precision <br />
</span><span style="color: #008000;">'http://www.kurims.kyoto-u.ac.jp/~ooura/index.html <br />
</span><span style="color: #008000;">'Copyright(C) 1996 Takuya OOURA : You may use, copy, modify this code for any purpose and without fee. <br />
</span><span style="color: #008000;">'Implementation en VBA par Philben - v1.0 <br />
</span> <br />
&nbsp; &nbsp;Const C0 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.12648096188977E-03 + 9.22E-18, C1 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.05739299623423E-04 + 4.7E-20, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C2 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.003512871461291 + 2.5E-19, C3 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 7.7170835895412E-04 + 9.39E-19, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C4 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 6.85649426074558E-03 + 6.12E-18, C5 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 3.39721910367775E-03 + 8.61E-18, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C6 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.12749169332504E-02 + 8.7E-17, C7 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.18598117047771E-02 + 1.04E-17, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C8 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.42961988697898E-02 + 1.8E-18, C9 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 3.46494207789099E-02 + 9.22E-17, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C10 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 2.20995927012179E-03 + 6.7E-19 <br />
&nbsp; &nbsp;Const C11 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 7.43424357241784E-02 + 8.61E-17, C12 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.105872177941595 + 4.88E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C13 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.47297938331485E-02 + 1.21E-17, C14 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.316847638520135 + 9.44E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C15 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.71365763586873 + 3.64E-16, C16 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.05375024970847 + 1.38E-15, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C17 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.21448730779995 + 2.37E-15, C18 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.1637458193156 + 8.31E-15, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C19 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.956464974744799 + 6E-18, C20 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.686265948274097 + 8.16E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C21 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.43439749233143 + 1.15E-16, C22 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.24404451059319 + 9.35E-16, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C23 <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0.120782237635245 + 2.22E-16 <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> s <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, t <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, u <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, w <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, X <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, z <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> y &gt; 1 <span style="color: #8D38C9; font-weight: bold;">Then</span> z = 2 - y <span style="color: #8D38C9; font-weight: bold;">Else</span>: z = y <br />
&nbsp; &nbsp;w = 0.916461398268964 - Log(z) <br />
&nbsp; &nbsp;u = Sqr(w) <br />
&nbsp; &nbsp;s = (Log(u) + 0.488826640273108) / w <br />
&nbsp; &nbsp;t = 1 / (u + 0.231729200323405) <br />
&nbsp; &nbsp;X = u * (1 - s * (s * 0.124610454613712 + 0.5)) - ((((-7.28846765585675E-02 * t + 0.269999308670029) * _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t + 0.150689047360223) * t + 0.116065025341614) * t + 0.499999303439796) * t <br />
&nbsp; &nbsp;t = 3.97886080735226 / (X + 3.97886080735226) <br />
&nbsp; &nbsp;u = t - 0.5 <br />
&nbsp; &nbsp;s = (((((((((C0 * u + C1) * u - C2) * u - C3) * u + C4) * u + C5) * u - C6) * u - C7) * u + C8) * u + C9) * u + C10 <br />
&nbsp; &nbsp;s = ((((((((((((s * u - C11) * u - C12) * u + C13) * u + C14) * u + C15) * u + C16) * u + C17) * u + _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; C18) * u + C19) * u + C20) * u + C21) * u + C22) * t - z * Exp(X * X - C23) <br />
&nbsp; &nbsp;X = X + (s * (X * s + 1)) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> y &gt; 1 <span style="color: #8D38C9; font-weight: bold;">Then</span> dierfc = -X <span style="color: #8D38C9; font-weight: bold;">Else</span>: dierfc = X <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>La fonction VBA pour calculer l&rsquo;inverse de la loi normale :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'--------------------------------------------------------------------------------------- <br />
</span><span style="color: #008000;">' Procédure &nbsp; &nbsp;: LoiNormaleInverse &nbsp; [Function] <br />
</span><span style="color: #008000;">' Auteur &nbsp; &nbsp; &nbsp; : Philben - Free to use <br />
</span><span style="color: #008000;">' Retour &nbsp; &nbsp; &nbsp; : Double <br />
</span><span style="color: #008000;">' Version &nbsp; &nbsp; &nbsp;: 2.0 <br />
</span><span style="color: #008000;">' Objet &nbsp; &nbsp; &nbsp; &nbsp;: Détermine la variable X d'une distribution normale en fonction de <br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: sa probabilité cumulée Pc, de la moyenne et de l'écart-type de la distribution <br />
</span><span style="color: #008000;">' Historique &nbsp; : v2.0 : Double précision (07/2012) <br />
</span><span style="color: #008000;">' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v1.0 : Simple précision (07/2007) <br />
</span><span style="color: #008000;">'--------------------------------------------------------------------------------------- <br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> LoiNormaleInverse(<span style="color: #151B8D; font-weight: bold;">ByVal</span> Pc <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Esperance <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> EcartType <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> Pc &lt;= 0 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; LoiNormaleInverse = -99 <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">ElseIf</span> Pc &gt;= 1 <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; LoiNormaleInverse = 99 <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span> <br />
&nbsp; &nbsp; &nbsp; LoiNormaleInverse = (-dierfc(Pc * 2) * EcartType * Sqr(2)) + Esperance <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Les paramètres sont la probabilité cumulée, l&rsquo;espérance et l&rsquo;écart-type de la distribution gaussienne pour lesquels on recherche X.</p>
<p><strong>Précision des résultats</strong><br />
Par comparaison avec les résultats de la fonction Excel NORM_S_DIST (notre référence Excel 2010) sur la plage de valeurs entre -8 et 8 de la loi normale standard avec un incrément de 1E-05, la plus grande différence relevée est de <strong>2,220E-16</strong> et une erreur relative maximum de 1,490E-14.</p>
<p><strong>Exemples</strong><br />
Coller l&rsquo;ensemble des fonctions dans un module standard VBA. Dans la fenêtre d&rsquo;exécution de l&rsquo;éditeur visual basic (CTRL + G pour la faire apparaître) coller la ou les lignes d&rsquo;exemples qui commence par ?, mettre le focus sur la ligne à exécuter puis appuyer sur la touche &lsquo;Entrée&rsquo; pour voir le résultat.</p>
<p><strong>Quelle est la probabilité pour qu&rsquo;une variable aléatoire X soit inférieure ou égale à 14 si elle suit la loi normale N(10,16) (espérance = 10 et variance = 16) ?</strong><br />
L&rsquo;aire sous la courbe de couleur bleue est la probabilité attendue :<br />
<img src="http://philben.developpez.com/LoiNormale1.png" alt="Exemple loi normale" title="Exemple loi normale" /></p>
<p>Sachant que l&rsquo;écart-type est la racine carrée de la variance :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Probabilité attendue : 0.841344746068543[/cci]<br />
</span>?LoiNormale(14,10,SQR(16))</div></div>
<p>Remarque : La loi normale est une loi continue de &#8211; l&rsquo;infini à + l&rsquo;infini et la probabilité que X soit égal à une valeur est pratiquement nulle (P(X = 14) = 0). Donc P(X <= 14) = P(X < 14).

<strong>Inversément, comment retrouver la variable X de cette probabilité ?</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'X attendu : 14<br />
</span>?LoiNormaleinverse(0.841344746068543,10,sqr(16))</div></div>
<p><strong>Quelle est la probabilité complémentaire de X : P(X > 14) (Aire verte de la courbe) ?</strong><br />
La loi normale est une loi symétrique, on peut donc écrire :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Probabilité attendue : 0.158655253931457<br />
</span>?1-LoiNormale(14,10,sqr(16))</div></div>
<p>ou encore :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Probabilité attendue : 0.158655253931457<br />
</span>?LoiNormale(10-(14-10),10,SQR(16))</div></div>
<p>Cette deuxième écriture est plus simple dans le cas d&rsquo;une loi normale centrée réduite N(0,1) :<br />
Exemple pour la probabilité complémentaire de X = 2 (P = 0.977249868051821 et 1-P = 2.27501319481792E-02)</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Probabilité attendue : 2,27501319481792E-02<br />
</span>?LoiNormale(-2)</div></div>
<p><strong>Remarque </strong>: Sous certaines conditions, la loi normale permet d&rsquo;approximer les lois de Poisson et Binomiale.</p>
<p><strong>Quelle est la probabilité que 7 <= X <= 9 sachant que X suit une loi normale N(8;2,25) (espérance = 8 et variance = 2,25) ?</strong><br />
La probabilité recherchée est l&rsquo;aire de la courbe verte :<br />
<img src="http://philben.developpez.com/LoiNormale2.png" alt="Loi normale" title="loi normale" /></p>
<p>Dans cet exemple, les écarts à l&rsquo;espérance sont symétrique (7 + 1 = 8 et 9 &#8211; 1 = 8) on peut écrire :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Probabilité attendue : 0.495014924906154 <br />
</span>?2*loinormale(9,8,sqr(2.25))-1<br />
<span style="color: #008000;">'Probabilité attendue : 0.495014924906154 <br />
</span>?1-2*loinormale(7,8,sqr(2.25))</div></div>
<p>Dans le cas général, il faut soustraire les deux probabilités. Par exemple pour 3 <= X <= 7 sachant que X suit une loi normale N(8;9), la formule devient :


<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Probabilité attendue : 0.321650987908949<br />
</span>?loinormale(7,8,3)-loinormale(3,8,3)</div></div>
<p><img src="http://philben.developpez.com/LoiNormale3.png" alt="Courbe en cloche" title="Courbe en cloche" /></p>
<p><strong>Exactitude des résultats</strong><br />
L&rsquo;objectif est d&rsquo;étudier succinctement l&rsquo;exactitude des résultats fournis par les fonctions Excel et les fonctions décrites ci-dessus.<br />
Pour ce faire je me suis servi comme référence des probabilités cumulées fournies par Maple 7 de la loi normale standard (avec plus de 16 chiffres significatifs) pour Z<=-1, Z<=-2, Z<=-3, ..., Z<=-37

Le 1er graphe affiche l'erreur relative commise sur l'approximation des probabilités en fonction de Z.
L'ordonnée est exprimée en log10 des erreurs relatives. Par exemple, le calcul de l'ordonnée avec la fonction Excel 2010 pour Z = -1 est :


<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Résultat attendu : 15.489451329628 <br />
</span>-Log(Abs(WorksheetFunction.Norm_S_Dist(-1, <span style="color: #00C2FF; font-weight: bold;">True</span>) - (0.158655253931457 + 5.141E-17))/ (0.158655253931457 + 5.141E-17)) / Log(10)</div></div>
<p>En pratique, il faut vérifier que la différence soit supérieure à zéro car Log(0) provoque une erreur&#8230;</p>
<p>Théoriquement, la valeur maximale est <strong>16</strong> lorsqu&rsquo;il n&rsquo;existe <strong>aucune différence</strong> entre les deux valeurs car le type Double a une précision de 16 chiffres (15 visibles + 1) : -Log(1E-16 / 1) / Log(10). Si on ne considère que les 15 chiffres visibles, l&rsquo;exactitude est déjà parfaite pour une valeur de 15.</p>
<p><strong>En résumé, plus la valeur du log de l&rsquo;erreur relative est élevée plus le résultat est exact.</strong></p>
<p><img src="http://philben.developpez.com/ErreurRelativeN.png" alt="Erreurs relatives sur N(0;1)" title="Erreurs relatives sur N(0;1)" /></p>
<p><strong>Les résultats entre Excel et Access sont très proches.</strong></p>
<p>Le 2ème graphe affiche l&rsquo;erreur relative commise sur l&rsquo;approximation de z en fonction des probabilités pour comparer les fonctions Norm_S_Inv() d&rsquo;Excel 2010 et LoiNormaleInverse().</p>
<p><img src="http://philben.developpez.com/ErreurRelativeZ.png" alt="Erreurs relatives sur Z" title="Erreurs relatives sur Z" /></p>
<p><strong>Les résultats entre Excel et Access sont très proches, on peut noter une petite faiblesse d&rsquo;Excel sur l&rsquo;approximation de z pour la 1ère probabilité (z=-1 théoriquement).</strong></p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Générer des nombres aléatoires gaussiens</title>
		<link>https://blog.developpez.com/philben/p11194/vba-access/generer_des_nombres_aleatoires_gaussiens</link>
		<comments>https://blog.developpez.com/philben/p11194/vba-access/generer_des_nombres_aleatoires_gaussiens#comments</comments>
		<pubDate>Mon, 30 Jul 2012 18:01:55 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Aléatoire]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Loi normale]]></category>
		<category><![CDATA[Numérique]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je vous présente ici deux petites fonctions écrites en VBA qui permettent de générer des nombres pseudo-aléatoires à distribution normale. Une fonction de visualisation accompagne le tout. La 1ère méthode implémentée est celle de Box-Muller Public Function NormalRandomBM(Optional ByVal Esperance &#8230; <a href="https://blog.developpez.com/philben/p11194/vba-access/generer_des_nombres_aleatoires_gaussiens">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Je vous présente ici deux petites fonctions écrites en VBA qui permettent de générer des nombres pseudo-aléatoires à distribution normale. Une fonction de visualisation accompagne le tout.<br />
<span id="more-12"></span><br />
<strong>La 1ère méthode implémentée est celle de Box-Muller</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> NormalRandomBM(<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Esperance <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> EcartType <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> ForceRandomize <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">False</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
<span style="color: #008000;">'Générateur de nombres pseudo-aléatoires à distribution normale selon la méthode de Box-Muller - Forme polaire <br />
</span><span style="color: #008000;">'Référence : http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform <br />
</span><span style="color: #008000;">'Implementation en VBA par Philben - v1.1 - Free to use <br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Static</span> isRandomize <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span>, isNextRandom <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span>, nextRandom <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> u <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, s <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> isRandomize <span style="color: #8D38C9; font-weight: bold;">Or</span> ForceRandomize <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; Randomize <br />
&nbsp; &nbsp; &nbsp; isRandomize = <span style="color: #00C2FF; font-weight: bold;">True</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> isNextRandom <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; NormalRandomBM = Esperance + (nextRandom * EcartType) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Do</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;u = Rnd() * 2 - 1 &nbsp; <span style="color: #008000;">'nombres aléatoires entre -1 et 1 <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; v = Rnd() * 2 - 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;s = u ^ 2 + v ^ 2 <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Loop</span> <span style="color: #8D38C9; font-weight: bold;">Until</span> s &gt; 0 <span style="color: #8D38C9; font-weight: bold;">And</span> s &lt; 1 <br />
&nbsp; &nbsp; &nbsp; s = Sqr(-2 * Log(s) / s) <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; nextRandom = v * s <br />
&nbsp; &nbsp; &nbsp; NormalRandomBM = Esperance + (u * s * EcartType) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp; &nbsp;isNextRandom = <span style="color: #8D38C9; font-weight: bold;">Not</span> isNextRandom <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>&nbsp;<br />
<strong>Particularité</strong><br />
Cet algorithme génère deux nombres pseudo-aléatoires gaussiens d&rsquo;où la possibilité d&rsquo;en conserver un pour l&rsquo;appel suivant de la fonction.<br />
On conserve un des deux nombres générés dans une variable <strong>Static</strong> qui sera utilisée au prochain appel pour réduire le temps de calcul de la fonction.</p>
<p><strong>Paramètres de la fonction de Box-Muller</strong><br />
Le premier paramètre est la moyenne mu ou l&rsquo;<strong>espérance</strong> de la distribution normale.<br />
Le deuxième est l&rsquo;écart-type de la distribution gaussienne (doit être supérieur à 0)<br />
Par défaut, l&rsquo;espérance est égale à 0 et l&rsquo;écart-type à 1 ce qui correspond aux paramètres de la loi normale centrée réduite N(0;1).<br />
Le troisième paramètre (par défaut à faux) permet de forcer la réinitialisation du générateur de nombre aléatoires de VBA (Randomize). Dans tous les cas, le premier appel de la fonction lance Randomize. Cette première initialisation est sauvegardée dans la variable Static <strong>isRandomize</strong> qui passe alors à l&rsquo;état Vrai.</p>
<p><strong>2ème méthode de Kinderman &#8211; Monahan</strong><br />
J&rsquo;ai ajouté cet algorithme car il est 30% plus rapide en VBA que le précédent et me permet de générer plus de 3 millions de nombres gaussiens par seconde.</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> NormalRandomKM(<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> Esperance <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 0, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> EcartType <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1, _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Optional</span> <span style="color: #151B8D; font-weight: bold;">ByVal</span> ForceRandomize <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> = <span style="color: #00C2FF; font-weight: bold;">False</span>) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
<span style="color: #008000;">'Générateur de nombres pseudo-aléatoires à distribution normale &nbsp;: Ratio method (Kinderman - Monahan) <br />
</span><span style="color: #008000;">'Implementation en VBA par Philben - v1.0 - Free to use <br />
</span> &nbsp; Const c <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 1.71552776992141 + 3.59296E-15 &nbsp; <span style="color: #008000;">'sqrt(8/e) <br />
</span> &nbsp; <span style="color: #151B8D; font-weight: bold;">Static</span> isRandomize <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Boolean</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> u <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, v <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span>, x <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> <span style="color: #8D38C9; font-weight: bold;">Not</span> isRandomize <span style="color: #8D38C9; font-weight: bold;">Or</span> ForceRandomize <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; Randomize <br />
&nbsp; &nbsp; &nbsp; isRandomize = <span style="color: #00C2FF; font-weight: bold;">True</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Do</span> <br />
&nbsp; &nbsp; &nbsp; v = Rnd() <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Do</span>: u = Rnd(): <span style="color: #8D38C9; font-weight: bold;">Loop</span> <span style="color: #8D38C9; font-weight: bold;">While</span> u = 0 <br />
&nbsp; &nbsp; &nbsp; x = (v - 0.5) * c / u <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Loop</span> <span style="color: #8D38C9; font-weight: bold;">Until</span> (x * x &lt; -4 * Log(u)) <br />
&nbsp;<br />
&nbsp; &nbsp;NormalRandomKM = Esperance + (x * EcartType) <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Les paramètres de la fonction sont identiques à la précédente.</p>
<p><strong>Limite des générateurs</strong><br />
Notre couple Randomize/Rnd n&rsquo;est pas une source parfaitement aléatoire de nombres entre 0 et 1[, on ne peut donc espérer un miracle concernant les nombres gaussiens générés&#8230; Dans l&rsquo;état, ces fonctions ne peuvent pas être utilisées pour un usage &lsquo;scientifique&rsquo;.<br />
Dans ce cas, il faudrait utiliser un meilleur générateur de nombres aléatoires type <strong>Mersenne Twister</strong> ou autres (<a href="http://blog.developpez.com/philben/p10822/ms-access-vba/un_meilleur_rng" title="Un meilleur RNG…" target="_blank">voir billet précédent</a>) et vérifier que la distribution est qualitativement correcte.</p>
<p><strong>Visualiser la distribution normale</strong><br />
La fonction suivante génère un visuel de la distribution normale centrée réduite des nombres aléatoires dans la fenêtre &lsquo;Exécution&rsquo; de l&rsquo;éditeur Visual Basic :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> VisuelNormalRandom()<br />
<span style="color: #008000;">'Visuel de la distribution des nombres aléatoires gaussiens - v1.1<br />
</span> &nbsp; Const cNbClasse <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> = 16, cNbEcartType <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = 4, cRangeClasse <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span> = cNbEcartType / cNbClasse<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, aCompte(-cNbClasse <span style="color: #8D38C9; font-weight: bold;">To</span> cNbClasse) <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, NumClasse <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, lMax <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span><br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> r <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Double</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = 1 <span style="color: #8D38C9; font-weight: bold;">To</span> 50000<br />
&nbsp; &nbsp; &nbsp; r = NormalRandomKM() / cRangeClasse<br />
&nbsp; &nbsp; &nbsp; NumClasse = Int(Abs(r))<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> Abs(r) &gt; NumClasse + 0.5 <span style="color: #8D38C9; font-weight: bold;">Then</span> NumClasse = NumClasse + 1<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> NumClasse &lt;= cNbClasse <span style="color: #8D38C9; font-weight: bold;">Then</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NumClasse = NumClasse * Sgn(r)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;aCompte(NumClasse) = aCompte(NumClasse) + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> aCompte(NumClasse) &gt; lMax <span style="color: #8D38C9; font-weight: bold;">Then</span> lMax = aCompte(NumClasse)<br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<br />
&nbsp; &nbsp;<span style="color: #008000;">'Affiche la distribution<br />
</span> &nbsp; Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> <span style="color: #800000;">&quot;Distribution des nombres aléatoires&quot;</span> &amp; vbCrLf &amp; <span style="color: #800000;">&quot;-----------------------------------&quot;</span><br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = <span style="color: #151B8D; font-weight: bold;">LBound</span>(aCompte) <span style="color: #8D38C9; font-weight: bold;">To</span> <span style="color: #151B8D; font-weight: bold;">UBound</span>(aCompte)<br />
&nbsp; &nbsp; &nbsp; r = i * cRangeClasse<br />
&nbsp; &nbsp; &nbsp; Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> IIf(Sgn(r) &gt;= 0, <span style="color: #800000;">&quot; &quot;</span>, <span style="color: #800000;">&quot;&quot;</span>) &amp; Format(r, <span style="color: #800000;">&quot;0.0#&quot;</span>), <span style="color: #F660AB; font-weight: bold;">String</span>(CDbl(aCompte(i)) / lMax * 50 + 1, <span style="color: #800000;">&quot;=&quot;</span>)<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i<br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Coller l&rsquo;ensemble des fonctions dans un module standard. Si la fenêtre d&rsquo;exécution n&rsquo;est pas visible, appuyer sur Ctrl+G puis mettre le focus dans la fonction précédente et appuyer sur F5 pour l&rsquo;exécuter.</p>
<p>Vous devriez obtenir à peu près ceci :<br />
<img src="http://philben.developpez.com/DistributionGaussienne.png" alt="Distribution gaussienne des nombres aléatoires" /></p>
<p>Théoriquement, 68% des nombres générés sont dans l&rsquo;intervalle + ou &#8211; 1 écart-type autour de la moyenne, 95% entre 2 écarts-types et 99,7% entre 3 écarts-types.</p>
<p>Pour aller plus loin sur le sujet, <a href="http://www.doc.ic.ac.uk/~wl/papers/07/csur07dt.pdf">cette publication</a> récente passe en revue de nombreuses méthodes et algorithmes.</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extraire les séries de valeurs</title>
		<link>https://blog.developpez.com/philben/p11017/sql-access/extraire_series_de_valeurs</link>
		<comments>https://blog.developpez.com/philben/p11017/sql-access/extraire_series_de_valeurs#comments</comments>
		<pubDate>Tue, 08 May 2012 16:52:44 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[Numérique]]></category>
		<category><![CDATA[Requête SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Un forumeur souhaitait connaître les séries de valeurs pour chaque famille et chaque donnee. Une requête permet de répondre à la question&#8230; Création de la table et insertion des données Public Function CreationFamille() &#160; &#160;Const cTable As String = &#34;tFamilles&#34; &#8230; <a href="https://blog.developpez.com/philben/p11017/sql-access/extraire_series_de_valeurs">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Un forumeur souhaitait connaître les séries de valeurs pour chaque famille et chaque donnee.<br />
Une requête permet de répondre à la question&#8230;<br />
<span id="more-23"></span><br />
<strong>Création de la table et insertion des données</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> CreationFamille() <br />
&nbsp; &nbsp;Const cTable <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;tFamilles&quot;</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">With</span> DoCmd <br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; .RunSQL <span style="color: #800000;">&quot;CREATE TABLE &quot;</span> &amp; cTable &amp; _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot; (Famille LONG, Donnee VARCHAR(15), Valeur INTEGER,&quot;</span> &amp; _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot; CONSTRAINT PrimaryKey PRIMARY KEY (Famille, Donnee, Valeur));&quot;</span> <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">True</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">With</span> <br />
&nbsp;<br />
&nbsp; &nbsp;InsertionFamilles <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span> <br />
&nbsp;<br />
<span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Sub</span> InsertionFamilles() <br />
&nbsp; &nbsp;Const cNombreFamille <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = 1 <br />
&nbsp; &nbsp;Const cTable <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;tFamilles&quot;</span> <br />
&nbsp; &nbsp;Const cInsert <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;INSERT INTO &quot;</span> &amp; cTable &amp; <span style="color: #800000;">&quot; VALUES &quot;</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">With</span> DoCmd <br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; i = Nz(DMax(<span style="color: #800000;">&quot;famille&quot;</span>, cTable)) + 1 <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = i <span style="color: #8D38C9; font-weight: bold;">To</span> i + cNombreFamille - 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'div', 1302);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'div', 1303);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'div', 1308);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1290);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1292);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1293);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1294);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1295);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1296);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1297);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">True</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">With</span> <br />
&nbsp; &nbsp;MsgBox <span style="color: #800000;">&quot;Création terminée&quot;</span> <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Sub</span></div></div>
<p><strong>Résultat attendu</strong></p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">famille &nbsp;donnee &nbsp;mini &nbsp;maxi <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;div &nbsp; &nbsp; 1302 &nbsp; 1303 <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;div &nbsp; &nbsp; 1308 &nbsp; 1308 <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;dov &nbsp; &nbsp; 1290 &nbsp; 1290 <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;dov &nbsp; &nbsp; 1292 &nbsp; 1297</div></div>
<p>Le groupe composé de la famille 1 et de la donnee &lsquo;div&rsquo; possède 2 séries de valeurs dont la première est composée de 2 nombres qui se suivent (1302 à 1303) et la seconde n&rsquo;est composée que d&rsquo;un seul nombre (1308).</p>
<p><strong>La requête SQL</strong></p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp;T<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; T<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">MIN</span><span style="color: #66cc66;">&#40;</span>T<span style="color: #66cc66;">.</span>mini<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> mini<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; T<span style="color: #66cc66;">.</span>maxi <span style="color: #993333; font-weight: bold;">AS</span> maxi<br />
&nbsp;<br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">AS</span> mini<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">MAX</span><span style="color: #66cc66;">&#40;</span>t2<span style="color: #66cc66;">.</span>valeur<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> maxi<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; &nbsp; tFamilles <span style="color: #993333; font-weight: bold;">AS</span> T1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">INNER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> tFamilles <span style="color: #993333; font-weight: bold;">AS</span> T2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> <span style="color: #66cc66;">&#40;</span>t1<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">&lt;=</span> t2<span style="color: #66cc66;">.</span>valeur<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AND</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>t1<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">=</span> t2<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">AND</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span>t1<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">=</span> t2<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; tfamilles T<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp;t<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">=</span> t1<span style="color: #66cc66;">.</span>famille<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">=</span> t1<span style="color: #66cc66;">.</span>donnee<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">BETWEEN</span> t1<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">AND</span> t2<span style="color: #66cc66;">.</span>valeur<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span>t2<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">-</span> T1<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> &nbsp; t1<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>valeur<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> T<br />
<span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> T<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;T<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;T<span style="color: #66cc66;">.</span>maxi<br />
<span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> T<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;T<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">MIN</span><span style="color: #66cc66;">&#40;</span>T<span style="color: #66cc66;">.</span>mini<span style="color: #66cc66;">&#41;</span>;</div></div>
<p><strong>Explications</strong><br />
On part d&rsquo;une auto jointure interne sur la table (&#8230;FROM tFamilles T1 INNER JOIN tFamilles T2&#8230;) qui nous permettra de confronter chaque valeur de tFamilles aux autres (un peu comme deux boucles For/Next imbriquées).<br />
Les contraintes de jointure (&#8230;ON t1.valeur&lt;=t2.valeur AND t1.famille=t2.famille AND t1.donnee=t2.donnee&#8230;) limitent les valeurs de T2 testées pour chaque valeur de T1 puisque l&rsquo;on souhaite connaître les séries par famille et donnee. De plus, on impose que les valeurs de T1 soient inférieures ou égales à celles de T2 pour faciliter la suite&#8230;</p>
<p>La clause WHERE contient une sous-requête (&#8230;SELECT COUNT(*)&#8230;) qui compte le nombre de lignes de la table tFamille entre T1.Valeur et T2.Valeur pour la famille et la donnee courante (&#8230;t.famille=t1.famille and t.donnee=t1.donnee&#8230;). Le nombre de lignes issues de cette sous-requête est comparé au nombre de lignes attendues entre T1.Valeur et T2.Valeur (Exemple : 1302 &#8211; 1300 + 1 = 3 valeurs [1300,1301,1302]) pour que la série entre ces deux valeurs soit complète.<br />
Si les deux nombres sont égaux, la série est complète et on la conserve.</p>
<p>A ce niveau là, on se retrouve avec toutes les séries intermédiaires entre le minimum et la maximum de chaque série complète entre t1.Valeur et T2.Valeur.<br />
Exemple : Pour la série complète 1300 à 1302 on obtient aussi les séries intermédiaires 1300 à 1300, 1300 à 1301, 1300 à 1302, 1301 à 1301, 1301 à 1302 et 1302 à 1302.</p>
<p>Il reste donc à trouver le minimum et la maximum de chaque série.<br />
Pour ce faire, on regroupe les données par famille, donnee et T1.Valeur (la valeur basse de chaque série) puis par la fonction d&rsquo;agrégation MAX(T2.Valeur) on retient la valeur maximale des séries qui commencent par T1.valeur. Dans notre exemple, on réduit donc les séries à : 1300 à <strong>1302</strong>, 1301 à <strong>1302</strong> et 1302 à <strong>1302</strong>.</p>
<p>Pour déterminer la valeur minimale des séries, on procède sur le même principe en regroupant par famille, donnee et maxi (valeur haute de chaque série que l&rsquo;on vient de déterminer). La fonction d&rsquo;agrégation MIN(T1.Valeur) donnera le minimum de chaque série, soit <strong>1300</strong> dans notre exemple.</p>
<p><strong>Performance</strong><br />
Les 3 colonnes appartiennent à la clef primaire ce qui permet à Access d&rsquo;utiliser un index qui optimise la requête.</p>
<p>Si vous souhaitez augmenter le nombre de lignes de la table, il suffit de modifier la valeur de la constante &lsquo;cNombreFamille&rsquo; (100 par exemple) de la fonction InsertionFamilles() et de la relancer. Eviter d&rsquo;insérer trop de lignes à la fois car RunSQL n&rsquo;est pas très rapide&#8230;</p>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Plages de trous entre les séries de valeurs</title>
		<link>https://blog.developpez.com/philben/p11020/sql-access/plages_de_trous_entre_les_series_de_vale</link>
		<comments>https://blog.developpez.com/philben/p11020/sql-access/plages_de_trous_entre_les_series_de_vale#comments</comments>
		<pubDate>Thu, 10 May 2012 19:04:15 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[SQL - Ms Access]]></category>
		<category><![CDATA[Numérique]]></category>
		<category><![CDATA[Requête SQL]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Faisant suite au billet précédent, on aurait pu vouloir les plages de trous entre les séries de valeurs pour chaque famille et donnee. Une requête permet d&#8217;y répondre&#8230; Création de la table et insertion des données Public Function CreationFamille() &#160; &#8230; <a href="https://blog.developpez.com/philben/p11020/sql-access/plages_de_trous_entre_les_series_de_vale">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Faisant suite au <a href="http://blog.developpez.com/philben/p11017/sql/extraire-series-de-valeurs/#more11017">billet précédent</a>, on aurait pu vouloir les plages de trous entre les séries de valeurs pour chaque famille et donnee.<br />
Une requête permet d&rsquo;y répondre&#8230;<br />
<span id="more-24"></span><br />
<strong>Création de la table et insertion des données</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> CreationFamille() <br />
&nbsp; &nbsp;Const cTable <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;tFamilles&quot;</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">With</span> DoCmd <br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; .RunSQL <span style="color: #800000;">&quot;CREATE TABLE &quot;</span> &amp; cTable &amp; _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot; (Famille LONG, Donnee VARCHAR(15), Valeur INTEGER,&quot;</span> &amp; _ <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #800000;">&quot; CONSTRAINT PrimaryKey PRIMARY KEY (Famille, Donnee, Valeur));&quot;</span> <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">True</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">With</span> <br />
&nbsp;<br />
&nbsp; &nbsp;InsertionFamilles <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span> <br />
&nbsp;<br />
<span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Sub</span> InsertionFamilles() <br />
&nbsp; &nbsp;Const cNombreFamille <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> = 1 <br />
&nbsp; &nbsp;Const cTable <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;tFamilles&quot;</span> <br />
&nbsp; &nbsp;Const cInsert <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">String</span> = <span style="color: #800000;">&quot;INSERT INTO &quot;</span> &amp; cTable &amp; <span style="color: #800000;">&quot; VALUES &quot;</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Integer</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">With</span> DoCmd <br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; i = Nz(DMax(<span style="color: #800000;">&quot;famille&quot;</span>, cTable)) + 1 <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = i <span style="color: #8D38C9; font-weight: bold;">To</span> i + cNombreFamille - 1 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'div', 1302);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'div', 1303);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'div', 1308);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1290);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1292);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1293);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1294);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1295);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1296);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1297);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1300);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.RunSQL cInsert &amp; <span style="color: #800000;">&quot;(&quot;</span> &amp; i &amp; <span style="color: #800000;">&quot;, 'dov', 1301);&quot;</span>, <span style="color: #00C2FF; font-weight: bold;">False</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; .SetWarnings <span style="color: #00C2FF; font-weight: bold;">True</span> <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">With</span> <br />
&nbsp; &nbsp;MsgBox <span style="color: #800000;">&quot;Création terminée&quot;</span> <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Sub</span></div></div>
<p><strong>Résultat attendu</strong></p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">famille &nbsp;donnee &nbsp;Mini &nbsp;Maxi <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;div &nbsp; &nbsp; 1304 &nbsp;1307 <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;dov &nbsp; &nbsp; 1291 &nbsp;1291 <br />
1 &nbsp; &nbsp; &nbsp; &nbsp;dov &nbsp; &nbsp; 1298 &nbsp;1299</div></div>
<p><strong>La requête SQL</strong></p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; &nbsp; &nbsp;t1<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Mini<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t2<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Maxi<br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; &nbsp; &nbsp;tFamilles <span style="color: #993333; font-weight: bold;">AS</span> T1<br />
<span style="color: #993333; font-weight: bold;">INNER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> &nbsp;tFamilles <span style="color: #993333; font-weight: bold;">AS</span> T2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> &nbsp;<span style="color: #66cc66;">&#40;</span> t1<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">=</span> t2<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> t1<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">=</span> t2<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">&lt;</span> T2<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp;<span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp;tfamilles T<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; t<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">=</span> t1<span style="color: #66cc66;">.</span>famille<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> t<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">=</span> t1<span style="color: #66cc66;">.</span>donnee<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> t<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">BETWEEN</span> t1<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">AND</span> t2<span style="color: #66cc66;">.</span>valeur<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">2</span>;</div></div>
<p><strong>Explications</strong><br />
Le principe de base (auto jointure interne) est le même que pour le billet précédent.<br />
Par la clause WHERE suivante &lsquo;t1.valeur &lt; T2.valeur &#8211; 1&prime;, on ne retient que les combinaisons de valeurs distantes (1 et 3 par exemple et non 1 et 2) puis la sous-requête compte le nombre de valeurs entre ces deux limites incluses. Si le compte est exactement égal à 2 on a donc un trou (gap pour les anglophones et autres&#8230;) dans la série.<br />
La plage de trous est comprise entre la valeur mini + 1 et la valeur maxi &#8211; 1.</p>
<p>Si l&rsquo;on souhaite aussi inclure les plages de trous externes aux valeurs de la table, une solution consiste à utiliser une requête UNION entre les deux limites choisies.<br />
Par exemple, pour retourner toutes les plages de trous entre <strong>1 et 2000 </strong>:</p>
<div class="codecolorer-container sql blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; &nbsp; &nbsp;t1<span style="color: #66cc66;">.</span>famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Mini<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t2<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Maxi<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; &nbsp; &nbsp;tFamilles <span style="color: #993333; font-weight: bold;">AS</span> T1<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">INNER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> &nbsp;tFamilles <span style="color: #993333; font-weight: bold;">AS</span> T2<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> &nbsp;<span style="color: #66cc66;">&#40;</span> t1<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">=</span> t2<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span> t1<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">=</span> t2<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; &nbsp; &nbsp; t1<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">&lt;</span> T2<span style="color: #66cc66;">.</span>valeur <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> <span style="color: #66cc66;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp;<span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp;tfamilles T<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp; t<span style="color: #66cc66;">.</span>famille <span style="color: #66cc66;">=</span> t1<span style="color: #66cc66;">.</span>famille<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> t<span style="color: #66cc66;">.</span>donnee <span style="color: #66cc66;">=</span> t1<span style="color: #66cc66;">.</span>donnee<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">AND</span> t<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">BETWEEN</span> t1<span style="color: #66cc66;">.</span>valeur <span style="color: #993333; font-weight: bold;">AND</span> t2<span style="color: #66cc66;">.</span>valeur<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">2</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; &nbsp; &nbsp;famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Mini<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">MIN</span><span style="color: #66cc66;">&#40;</span>valeur<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Maxi<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; &nbsp; &nbsp;tFamilles<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> &nbsp; &nbsp;famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; donnee<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">HAVING</span> &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">MIN</span><span style="color: #66cc66;">&#40;</span>valeur<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">1</span><br />
<span style="color: #993333; font-weight: bold;">UNION</span><br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">SELECT</span> &nbsp; &nbsp;famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; donnee<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">MAX</span><span style="color: #66cc66;">&#40;</span>valeur<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> Mini<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">2000</span> <span style="color: #993333; font-weight: bold;">AS</span> Maxi<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; &nbsp; &nbsp;tFamilles<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">GROUP</span> <span style="color: #993333; font-weight: bold;">BY</span> &nbsp;famille<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; donnee<br />
&nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">HAVING</span> &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">MAX</span><span style="color: #66cc66;">&#40;</span>valeur<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">2000</span>;</div></div>
<p>@+</p>
<p>Philippe</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Indexer un tri de tableau</title>
		<link>https://blog.developpez.com/philben/p10858/vba-access/indexer_un_tri_de_tableau</link>
		<comments>https://blog.developpez.com/philben/p10858/vba-access/indexer_un_tri_de_tableau#comments</comments>
		<pubDate>Tue, 20 Mar 2012 20:40:41 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Numérique]]></category>
		<category><![CDATA[Tableau]]></category>
		<category><![CDATA[Trier]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Dans certaines circonstances, il est nécessaire de ne pas trier le tableau originel mais d&#8217;indexer le tri dans un tableau secondaire. Voici la fonction de tri indexé avec Shellsort&#8230; 'ShellsortIndex - Philben - v1.0 - 03/2012 'Utilisable pour des tailles &#8230; <a href="https://blog.developpez.com/philben/p10858/vba-access/indexer_un_tri_de_tableau">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Dans certaines circonstances, il est nécessaire de ne pas trier le tableau originel mais d&rsquo;indexer le tri dans un tableau secondaire.<br />
Voici la fonction de tri indexé avec Shellsort&#8230;<br />
<span id="more-5"></span></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'ShellsortIndex - Philben - v1.0 - 03/2012 <br />
</span><span style="color: #008000;">'Utilisable pour des tailles de tableau jusqu'à 10 000 000 <br />
</span><span style="color: #008000;">'Les valeurs des gaps au-dessus de 1750 sont extrapolées et ne sont certainement pas les plus efficaces ! <br />
</span><span style="color: #008000;">'Si le type de tableau est Integer, modifier : <br />
</span><span style="color: #008000;">' &nbsp;- ByRef a() As Long &nbsp; &nbsp; en ByRef a() As Integer <br />
</span><span style="color: #008000;">' &nbsp;- Dim ref As Long &nbsp; &nbsp; &nbsp; en Dim ref As Integer <br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> ShellSortIndex(<span style="color: #151B8D; font-weight: bold;">ByRef</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">ByRef</span> Idx() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> lowerBound <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> upperBound <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>) <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> ref <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> h <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, l <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, m <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, n <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, refIdx <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, g <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">ReDim</span> Idx(lowerBound <span style="color: #8D38C9; font-weight: bold;">To</span> upperBound) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = lowerBound <span style="color: #8D38C9; font-weight: bold;">To</span> upperBound: Idx(i) = i: <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp;<br />
&nbsp; &nbsp;g = Array(1, 4, 10, 23, 57, 132, 301, 701, 1750, 4376, 10941, 27353, 68383, 170958, 427396, 1068491, 2671228) <br />
&nbsp; &nbsp;n = upperBound - lowerBound + 1 <br />
&nbsp;<br />
&nbsp; &nbsp;l = <span style="color: #151B8D; font-weight: bold;">LBound</span>(g) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> n &lt; g(<span style="color: #151B8D; font-weight: bold;">UBound</span>(g)) <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; k = l <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">While</span> g(k + 1) &lt; n: k = k + 1: Wend <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span> <br />
&nbsp; &nbsp; &nbsp; k = <span style="color: #151B8D; font-weight: bold;">UBound</span>(g) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">While</span> k &gt;= l <br />
&nbsp; &nbsp; &nbsp; h = g(k) <br />
&nbsp; &nbsp; &nbsp; m = lowerBound + h <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = m <span style="color: #8D38C9; font-weight: bold;">To</span> upperBound <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ref = a(Idx(i)) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;refIdx = Idx(i) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = i <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Do</span> <span style="color: #8D38C9; font-weight: bold;">While</span> ref &lt; a(Idx(j - h)) &nbsp; <span style="color: #008000;">'&lt; pour un tri croissant, sinon &gt; <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Idx(j) = Idx(j - h) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = j - h <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> j &lt; m <span style="color: #8D38C9; font-weight: bold;">Then</span> <span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #8D38C9; font-weight: bold;">Do</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Loop</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Idx(j) = refIdx <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp; &nbsp; k = k - 1 <br />
&nbsp; &nbsp;Wend <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p>Le tableau Idx() contient l&rsquo;ordre des valeurs du tableau a().<br />
Par exemple, Les valeurs triées sont obtenues par :</p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">For</span> i = <span style="color: #151B8D; font-weight: bold;">LBound</span>(Idx) <span style="color: #8D38C9; font-weight: bold;">To</span> <span style="color: #151B8D; font-weight: bold;">UBound</span>(Idx)<br />
&nbsp; &nbsp; &nbsp; Debug.<span style="color: #151B8D; font-weight: bold;">Print</span> a(Idx(i))<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Next</span> i</div></div>
<p><strong>Remarque</strong><br />
Le tri par index est moins rapide que le tri du tableau lui-même. Compter 40 à 50% de temps en plus.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fonction performante de tri de tableaux</title>
		<link>https://blog.developpez.com/philben/p10854/vba-access/fonction_performante_de_tri_de_tableaux</link>
		<comments>https://blog.developpez.com/philben/p10854/vba-access/fonction_performante_de_tri_de_tableaux#comments</comments>
		<pubDate>Mon, 19 Mar 2012 22:08:37 +0000</pubDate>
		<dc:creator><![CDATA[philben]]></dc:creator>
				<category><![CDATA[VBA - Ms Access]]></category>
		<category><![CDATA[Algorithme]]></category>
		<category><![CDATA[Code VBA]]></category>
		<category><![CDATA[Numérique]]></category>
		<category><![CDATA[Tableau]]></category>
		<category><![CDATA[Trier]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il existe plusieurs dizaines de méthodes de tri de tableaux et la plus renommée est Quicksort en terme de rapidité. Qu&#8217;en est-il en VBA ? J&#8217;ai testé plusieurs algorithmes dont Insertionsort, Heapsort, Mergesort, Quicksort, mais mon préféré reste Shellsort par &#8230; <a href="https://blog.developpez.com/philben/p10854/vba-access/fonction_performante_de_tri_de_tableaux">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Il existe plusieurs dizaines de méthodes de tri de tableaux et la plus renommée est Quicksort en terme de rapidité.<br />
Qu&rsquo;en est-il en VBA ?<br />
<span id="more-4"></span><br />
J&rsquo;ai testé plusieurs algorithmes dont Insertionsort, Heapsort, Mergesort, Quicksort, mais mon préféré reste Shellsort par sa compacité, simplicité et sa rapidité. L&rsquo;efficacité de Shellsort réside dans le choix des gaps qui ont fait l&rsquo;objet de multiples publications depuis les années 60. Les meilleurs gaps semblent bien définis jusqu&rsquo;à la valeur de 1750.</p>
<p><strong>Ma fonction Shellsort</strong></p>
<div class="codecolorer-container vb blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><div class="vb codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000;">'Shellsort - Philben - v1.0 - 03/2012 <br />
</span><span style="color: #008000;">'Utilisable pour des tailles de tableau jusqu'à 10 000 000 <br />
</span><span style="color: #008000;">'La valeur des gaps au-dessus de 1750 sont extrapolées et ne sont certainement pas les plus efficaces ! <br />
</span><span style="color: #008000;">'Si le type de tableau est Integer, modifier : <br />
</span><span style="color: #008000;">' &nbsp;- ByRef a() As Long &nbsp;en ByRef a() As Integer <br />
</span><span style="color: #008000;">' &nbsp;- Dim ref As Long &nbsp; &nbsp;en Dim ref As Integer <br />
</span><span style="color: #E56717; font-weight: bold;">Public</span> <span style="color: #E56717; font-weight: bold;">Function</span> ShellSort(<span style="color: #151B8D; font-weight: bold;">ByRef</span> a() <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> lowerBound <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, <span style="color: #151B8D; font-weight: bold;">ByVal</span> upperBound <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>) <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> ref <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span> <br />
&nbsp; &nbsp;<span style="color: #151B8D; font-weight: bold;">Dim</span> h <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, i <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, j <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, k <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, l <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, m <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, n <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Long</span>, g <span style="color: #151B8D; font-weight: bold;">As</span> <span style="color: #F660AB; font-weight: bold;">Variant</span> <br />
&nbsp;<br />
&nbsp; &nbsp;g = Array(1, 4, 10, 23, 57, 132, 301, 701, 1750, 4376, 10941, 27353, 68383, 170958, 427396, 1068491, 2671228) <br />
&nbsp; &nbsp;n = upperBound - lowerBound + 1 <br />
&nbsp;<br />
&nbsp; &nbsp;l = <span style="color: #151B8D; font-weight: bold;">LBound</span>(g) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">If</span> n &lt; g(<span style="color: #151B8D; font-weight: bold;">UBound</span>(g)) <span style="color: #8D38C9; font-weight: bold;">Then</span> <br />
&nbsp; &nbsp; &nbsp; k = l <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">While</span> g(k + 1) &lt; n: k = k + 1: Wend <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Else</span> <br />
&nbsp; &nbsp; &nbsp; k = <span style="color: #151B8D; font-weight: bold;">UBound</span>(g) <br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #8D38C9; font-weight: bold;">If</span> <br />
&nbsp;<br />
&nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">While</span> k &gt;= l <br />
&nbsp; &nbsp; &nbsp; h = g(k) <br />
&nbsp; &nbsp; &nbsp; m = lowerBound + h <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">For</span> i = m <span style="color: #8D38C9; font-weight: bold;">To</span> upperBound <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ref = a(i) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;j = i <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Do</span> <span style="color: #8D38C9; font-weight: bold;">While</span> ref &lt; a(j - h) <span style="color: #008000;">'&lt; pour un tri croissant, sinon &gt; <br />
</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a(j) = a(j - h) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = j - h <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">If</span> j &lt; m <span style="color: #8D38C9; font-weight: bold;">Then</span> <span style="color: #E56717; font-weight: bold;">Exit</span> <span style="color: #8D38C9; font-weight: bold;">Do</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #8D38C9; font-weight: bold;">Loop</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a(j) = ref <br />
&nbsp; &nbsp; &nbsp; <span style="color: #8D38C9; font-weight: bold;">Next</span> i <br />
&nbsp; &nbsp; &nbsp; k = k - 1 <br />
&nbsp; &nbsp;Wend <br />
<span style="color: #8D38C9; font-weight: bold;">End</span> <span style="color: #E56717; font-weight: bold;">Function</span></div></div>
<p><strong>Le face à face</strong><br />
Après avoir trouvé sur le <a href="http://epaperpress.com/sortsearch/index.html">web</a> une bonne implémentation de Qsort (Quicksort non récursif), j&rsquo;ai comparé leur rapidité à trier différentes tailles de tableau.<br />
Les résultats de Shellsort en prenant comme base 100 les résultats de Qsort pour le tri d&rsquo;entiers long :<br />
<img src="http://philben.developpez.com/shellsort.png" alt="Shellsort" title="Performance de Shellsort par rapport à Qsort" /></p>
<p><strong>Analyse des résultats</strong><br />
Shellsort est plus rapide (jusqu&rsquo;à 30% plus rapide !) que Qsort pour des tableaux inférieurs à 100 000 valeurs. Au-delà, Qsort creuse petit à petit l&rsquo;écart.<br />
Compter une dizaine de millisecondes pour trier un tableau de 10 000 valeurs, 160ms pour 100 000 et 2 secondes pour 1 million de valeurs.</p>
<p><strong>Conclusion</strong><br />
En VBA et pour des tableaux jusqu&rsquo;à 100 000 valeurs, Shellsort est un algorithme de tri très rapide. Si vous possédez une fonction encore plus rapide, merci de l&rsquo;ajouter en commentaire.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
