SceL 0 Denunciar post Postado Abril 3, 2011 Estava eu a desenvolver um sistema para minha empresa, e me deparo com uma fato curioso. Tenho um campo chamado Inicial, Tenho um campo chamado Final. Dentro de um campo inicial colocamos o valor inicial por exempo 1. Dentro de um campo final colocamos o valor final por exemplo 2. O sistema vai cadastrar dentro de um banco de dados todos os valores FLOATs com 2 casas decimais ( 1 1.01 1.02 ... 1.99 2 ) dando um total de 101 números. Mas vem o porém, não é permitido cadastrar números repetidos, por exemplo se previamente cadastrei 1.10 até 1.20 os numeros e seus meios, não deverão ser cadastrados. Imaginei o seguinte: Farei uma busca no banco com SELECT * FROM `banco` WHERE `valor` >= '" . $_POST['valorInicial'] . "' AND `valorFinal` <= '" . $_POST['valorFinal'] . "' Retorna todos os valores certinhos que eu procurava: 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 Isso eu dando um echo. Joguei todos os valores em uma array previamente criada e "global" para os ifs elses e fors que os utlizarão. E a cada valor com um while ( $valores = mysql_fetch_array($busca) ) dou um array_push($valores['valor'],$array); Ou seja a array guardará todos os valores anteriormente exibidos com o echo: 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 Dou um print_r($array); Exibe todos sem erro nenhum! Um sucesso. Até ai tudo bem. Agora na hora de inserir no banco, os valores de 1 até 2 faço da seguinte forma; for ($i = $_POST['valorInicial']; $i <= $_POST['valorFinal']; $i += 0.01) { [indent]if (!in_array($i,$arrays)) mysql_fetch_row("INSERT INTO `banco` VALUES (null,'" . $i . "','" . $_SESSION['idUsuarioLogado'] . "')");[/indent] } Todos os valores são realmente inseridos perfeitamente. Então teremos todos os valores de 1 Até 2 Cadastrados ou seja os 101 números. Após eu inserir esses números de 1 até 2, se eu tentar inserir os números de 1 até 2.1 ou seja ele inseria os números de 2.01 até 2.1 ( 2.01 2.02 2.03 ... 2.09 2.1); Mas pelo meio não sei o que acontece mas o in_array buga e ele adiciona os valores (1.14 1.36 1.39 1.57 1.59 1.61 1.64 1.66 1.68 1.82 1.84 1.86 1.89 1.91 1.93 2.01 2.02 2.03 2.04 2.05 2.06 2.07 2.08 2.09 2.1) O PHP não pega valores aleatórios, sempre esses. Não posso por o campo no banco como UNIQUE pois ta assossiado a cada id de Usuário Logado onde podem se repetir numeros. Saidas do sistema: echo $valores['valor'] . " "; É exibido corretamente (Valores já cadastrados no banco): 1 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.2 1.21 1.22 1.23 1.24 1.25 1.26 1.27 1.28 1.29 1.3 1.31 1.32 1.33 1.34 1.35 1.36 1.37 1.38 1.39 1.4 1.41 1.42 1.43 1.44 1.45 1.46 1.47 1.48 1.49 1.5 1.51 1.52 1.53 1.54 1.55 1.56 1.57 1.58 1.59 1.6 1.61 1.62 1.63 1.64 1.65 1.66 1.67 1.68 1.69 1.7 1.71 1.72 1.73 1.74 1.75 1.76 1.77 1.78 1.79 1.8 1.81 1.82 1.83 1.84 1.85 1.86 1.87 1.88 1.89 1.9 1.91 1.92 1.93 1.94 1.95 1.96 1.97 1.98 1.99 2 print_r($arrays); É exibido corretamente (Valores já cadastrados no banco com saida pela array): Array ( [0] => 1 [1] => 1.01 [2] => 1.02 [3] => 1.03 [4] => 1.04 [5] => 1.05 [6] => 1.06 [7] => 1.07 [8] => 1.08 [9] => 1.09 [10] => 1.1 [11] => 1.11 [12] => 1.12 [13] => 1.13 [14] => 1.14 [15] => 1.15 [16] => 1.16 [17] => 1.17 [18] => 1.18 [19] => 1.19 [20] => 1.2 [21] => 1.21 [22] => 1.22 [23] => 1.23 [24] => 1.24 [25] => 1.25 [26] => 1.26 [27] => 1.27 [28] => 1.28 [29] => 1.29 [30] => 1.3 [31] => 1.31 [32] => 1.32 [33] => 1.33 [34] => 1.34 [35] => 1.35 [36] => 1.36 [37] => 1.37 [38] => 1.38 [39] => 1.39 [40] => 1.4 [41] => 1.41 [42] => 1.42 [43] => 1.43 [44] => 1.44 [45] => 1.45 [46] => 1.46 [47] => 1.47 [48] => 1.48 [49] => 1.49 [50] => 1.5 [51] => 1.51 [52] => 1.52 [53] => 1.53 [54] => 1.54 [55] => 1.55 [56] => 1.56 [57] => 1.57 [58] => 1.58 [59] => 1.59 [60] => 1.6 [61] => 1.61 [62] => 1.62 [63] => 1.63 [64] => 1.64 [65] => 1.65 [66] => 1.66 [67] => 1.67 [68] => 1.68 [69] => 1.69 [70] => 1.7 [71] => 1.71 [72] => 1.72 [73] => 1.73 [74] => 1.74 [75] => 1.75 [76] => 1.76 [77] => 1.77 [78] => 1.78 [79] => 1.79 [80] => 1.8 [81] => 1.81 [82] => 1.82 [83] => 1.83 [84] => 1.84 [85] => 1.85 [86] => 1.86 [87] => 1.87 [88] => 1.88 [89] => 1.89 [90] => 1.9 [91] => 1.91 [92] => 1.92 [93] => 1.93 [94] => 1.94 [95] => 1.95 [96] => 1.96 [97] => 1.97 [98] => 1.98 [99] => 1.99 [100] => 2 ) if (!in_array($i,$arrays)) echo $i . " "; É exibido com erro: 1.14 1.36 1.39 1.57 1.59 1.61 1.64 1.66 1.68 1.82 1.84 1.86 1.89 1.91 1.93 2.01 2.02 2.03 2.04 2.05 2.06 2.07 2.08 2.09 2.1 Se alguém ja teve problema parecido com o in_array peço humildemente que me diga como proceder. PS.: com um loop para a array usando comparação $i != $arrays[j], funciona normal, mas creio o loop ser maior, e deixar meu código fonte mais feio. Mas não tendo jeito voltarei a ele! Compartilhar este post Link para o post Compartilhar em outros sites
Matheus Tavares 167 Denunciar post Postado Abril 3, 2011 É, meu amigo. Parece que encontramos um bug do PHP. Pelo menos não vejo motivos para o seguinte estar ocorrendo: <?php $inicial = 1.4; //A UNICA ALTERACAO ENTRE OS DOIS SCRIPTS ESTÁ NESSA LINHA ########################################################################## for ($i = $inicial; $i <= 1.6; $i += 0.01) { $array[] = $i; } $i = 1.55; echo '<pre>'; print_r($array); echo (array_search($i, $array)) ? $i : 'N'; Resultado: Array( [0] => 1.4 [1] => 1.41 [2] => 1.42 [3] => 1.43 [4] => 1.44 [5] => 1.45 [6] => 1.46 [7] => 1.47 [8] => 1.48 [9] => 1.49 [10] => 1.5 [11] => 1.51 [12] => 1.52 [13] => 1.53 [14] => 1.54 [15] => 1.55 [16] => 1.56 [17] => 1.57 [18] => 1.58 [19] => 1.59 [20] => 1.6 ) 1.55 Até aí tudo certo. Fez o loop, procurou, encontrou. (usei array_search, mas in_array retornou o mesmo resultado nos dois scripts) <?php $inicial = 1.3; //A UNICA ALTERACAO ENTRE OS DOIS SCRIPTS ESTÁ NESSA LINHA ########################################################################## for ($i = $inicial; $i <= 1.6; $i += 0.01) { $array[] = $i; } $i = 1.55; echo '<pre>'; print_r($array); echo (array_search($i, $array)) ? $i : 'N'; Alterei o inicial para 1.3, aumentando o número de registros, e não encontrou, mesmo estando ali. Array( [0] => 1.3 [1] => 1.31 [2] => 1.32 [3] => 1.33 [4] => 1.34 [5] => 1.35 [6] => 1.36 [7] => 1.37 [8] => 1.38 [9] => 1.39 [10] => 1.4 [11] => 1.41 [12] => 1.42 [13] => 1.43 [14] => 1.44 [15] => 1.45 [16] => 1.46 [17] => 1.47 [18] => 1.48 [19] => 1.49 [20] => 1.5 [21] => 1.51 [22] => 1.52 [23] => 1.53 [24] => 1.54 [25] => 1.55 [26] => 1.56 [27] => 1.57 [28] => 1.58 [29] => 1.59 ) N Fiz diversos testes, e acredito que realmente seja um bug do PHP. Procurei na buglist e encontrei muitos tópicos relacionados (tipagens/in_array/array_search), mas nenhum exatamente sobre isso. Minha solução foi inutilizar o tipo float/double, convertendo a variável para tipo string. Segue código/resultado: <?php $inicial = 1.3; ########################################################################## for ($i = $inicial; $i <= 1.6; $i += 0.01) { $array[] = (string)$i; //transformei cada valor do array em string } $i = 1.55; echo '<pre>'; print_r($array); echo (array_search((string)$i, $array)) ? $i : 'N'; Resultado: Array( [0] => 1.3 [1] => 1.31 [2] => 1.32 [3] => 1.33 [4] => 1.34 [5] => 1.35 [6] => 1.36 [7] => 1.37 [8] => 1.38 [9] => 1.39 [10] => 1.4 [11] => 1.41 [12] => 1.42 [13] => 1.43 [14] => 1.44 [15] => 1.45 [16] => 1.46 [17] => 1.47 [18] => 1.48 [19] => 1.49 [20] => 1.5 [21] => 1.51 [22] => 1.52 [23] => 1.53 [24] => 1.54 [25] => 1.55 [26] => 1.56 [27] => 1.57 [28] => 1.58 [29] => 1.59 ) 1.55 Cara, peço desculpas se não era essa sua dúvida. Juro que li três vezes e não entendi com clareza. Daí comecei a criar alguns testes, e me deparei com esse problema, espero que ajude! Um abraço! Compartilhar este post Link para o post Compartilhar em outros sites
William Bruno 1501 Denunciar post Postado Abril 3, 2011 realmente tem algum problema aqui começando em 1.3 var_dump( $i, $array[25], $i==$array[25] ); saída: float(1.55)float(1.55) bool(false) e no outro caso, começando em 1.4 var_dump( $i, $array[15], $i==$array[15] ); float(1.55)float(1.55) bool(true) Compartilhar este post Link para o post Compartilhar em outros sites
André Severino 3 Denunciar post Postado Abril 3, 2011 Estava até agora testando também e não achei, mas estava achando que era eu quem tava errando. Compartilhar este post Link para o post Compartilhar em outros sites
SceL 0 Denunciar post Postado Abril 3, 2011 É mais ou menos isso que você fez. E sim me pareceu um bug do PHP. Também me deparei com um bug do MySQL no mesmo sistema mas o contornei. Se quiserem testar façam o seguinte. Cria um banco de dados e insere valores no banco tipo os que passei ( o campo com esses valores deve ser float ): 1.2 1.21 1.22 1.23 1.24 1.25 1.26 1.27 1.28 etc. tento dotos esses valores por exemplo de 1 até 2. Teríamos: 1 1.01 1.02 1.03 1.04 ... 1.99 2 Faça uma busca no banco por exemplo dos números entre 1.1 e 1.2 o banco vai retornar: ( SELECT * FROM `banco` WHERE `valor` >= 1.1 AND `valor` <= 1.2 ) Resultados obtidos: 1.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.2 Está correto. Mas caso você faça a busca por um só valor, por exemplo 1.13 o banco retorna zero registros! ( SELECT * FROM `banco` WHERE `valor` = 1.13 ) Retorno : Zero Registros Para contornar isso substitui os valores float por double e funcionou. Compartilhar este post Link para o post Compartilhar em outros sites
Matheus Tavares 167 Denunciar post Postado Abril 3, 2011 Para contornar isso substitui os valores float por double e funcionou. Então está resolvido? Compartilhar este post Link para o post Compartilhar em outros sites
SceL 0 Denunciar post Postado Abril 3, 2011 O que funcionou foi a busca no banco de dados, sobre este mesmo problema não funcionouu e ainda fiz um novo post de um problema parecido! Fiz testes com variáveis maiores ou iguais a 2 não da o mesmo problema. Se o número por exemplo for inicial de 2.01 e final 3 funciona normal! Compartilhar este post Link para o post Compartilhar em outros sites
Matheus Tavares 167 Denunciar post Postado Abril 3, 2011 Mas você chegou a ver a solução que utilizei no post #2? Ela não serve? Compartilhar este post Link para o post Compartilhar em outros sites
SceL 0 Denunciar post Postado Abril 4, 2011 O erro não é o in_array e sim o mesmo problema que aconteceu no meu outro tópico que ja foi resolvido. Alguns valores no float tem resquicios nas casas decimais de valores, por exemplo: $valor = 1.1; echo printf("%.20f %.20f\n", intval($valor * 100), ($valor * 100) ); exibirão valores diferentes: 110.00000000000000000000 110.00000000000001421085 Para contornar isso fiz assim: $valor = 1.1; $esperado = trim( intval(trim($valor * 100 . " ")) . " "); $recebido = trim( $valor * 100 . " " ); É um POG ( Programação Orientada a Gambiarra ) mas esse bug tosco precisa ser contornado de alguma maneira! Grato aos que tentaram ajudar. Compartilhar este post Link para o post Compartilhar em outros sites
romabeckman 0 Denunciar post Postado Abril 4, 2011 Olá, SceL e Matheus Tavares a minha opinião é que, não acredito que seja um bug do PHP. Na verdade o laço no for é para contadores inteiros. Assim o incremente deve ser inteiro. Neste mesmo caso acredito que um laço do {...} while(condição); resolve o problema. Veja o exemplo abaixo: $array = array(); $increment = 0.01; $cont = 1; $fim = 2; do{ $array[] = $cont; $cont += $increment; } while($cont <= $fim); echo "<pre>"; var_dump($array); $array2 = array(); $cont = 1; $fim = 2; do{ if(!in_array($cont, $array)){ $array2[] = $cont; } $cont += $increment; } while($cont <= $fim); echo "<pre>"; var_dump($array2); Imprime: array(100) { [0]=> int(1) [1]=> float(1.01) [2]=> float(1.02) [3]=> float(1.03) [4]=> float(1.04) [5]=> float(1.05) [6]=> float(1.06) [7]=> float(1.07) [8]=> float(1.08) [9]=> float(1.09) [10]=> float(1.1) [11]=> float(1.11) [12]=> float(1.12) [13]=> float(1.13) [14]=> float(1.14) [15]=> float(1.15) [16]=> float(1.16) [17]=> float(1.17) [18]=> float(1.18) [19]=> float(1.19) [20]=> float(1.2) [21]=> float(1.21) [22]=> float(1.22) [23]=> float(1.23) [24]=> float(1.24) [25]=> float(1.25) [26]=> float(1.26) [27]=> float(1.27) [28]=> float(1.28) [29]=> float(1.29) [30]=> float(1.3) [31]=> float(1.31) [32]=> float(1.32) [33]=> float(1.33) [34]=> float(1.34) [35]=> float(1.35) [36]=> float(1.36) [37]=> float(1.37) [38]=> float(1.38) [39]=> float(1.39) [40]=> float(1.4) [41]=> float(1.41) [42]=> float(1.42) [43]=> float(1.43) [44]=> float(1.44) [45]=> float(1.45) [46]=> float(1.46) [47]=> float(1.47) [48]=> float(1.48) [49]=> float(1.49) [50]=> float(1.5) [51]=> float(1.51) [52]=> float(1.52) [53]=> float(1.53) [54]=> float(1.54) [55]=> float(1.55) [56]=> float(1.56) [57]=> float(1.57) [58]=> float(1.58) [59]=> float(1.59) [60]=> float(1.6) [61]=> float(1.61) [62]=> float(1.62) [63]=> float(1.63) [64]=> float(1.64) [65]=> float(1.65) [66]=> float(1.66) [67]=> float(1.67) [68]=> float(1.68) [69]=> float(1.69) [70]=> float(1.7) [71]=> float(1.71) [72]=> float(1.72) [73]=> float(1.73) [74]=> float(1.74) [75]=> float(1.75) [76]=> float(1.76) [77]=> float(1.77) [78]=> float(1.78) [79]=> float(1.79) [80]=> float(1.8) [81]=> float(1.81) [82]=> float(1.82) [83]=> float(1.83) [84]=> float(1.84) [85]=> float(1.85) [86]=> float(1.86) [87]=> float(1.87) [88]=> float(1.88) [89]=> float(1.89) [90]=> float(1.9) [91]=> float(1.91) [92]=> float(1.92) [93]=> float(1.93) [94]=> float(1.94) [95]=> float(1.95) [96]=> float(1.96) [97]=> float(1.97) [98]=> float(1.98) [99]=> float(1.99) } array(0) { } Espero ter ajudado!!! Compartilhar este post Link para o post Compartilhar em outros sites
Matheus Tavares 167 Denunciar post Postado Abril 4, 2011 romabeckman, agradeço pelas sugestões, mas infelizmente elas não fazem sentido. O for trabalha sim com qualquer condição de loop, e não há nenhuma limitação explícita no manual do PHP nesse sentido. Você não deve ter lido o post do William Bruno, onde sequer fora utilizado loopings. Veja um exemplo com "do { } while;": <?php $i = 1.3; do { $array[] = $i; $i += 0.01; } while ($i <= 1.6); $i = 1.55; echo '<pre>'; print_r($array); echo (array_search($i, $array)) ? $i : 'N'; //vai retornar N, pois por algum motivo não encontrou no array. Isso é sim um bug do PHP, e acontece por causa do que foi explicado no post #9 pelo SceL. :thumbsup: Compartilhar este post Link para o post Compartilhar em outros sites
romabeckman 0 Denunciar post Postado Abril 5, 2011 Verdade, eu estava errado... Vlw Matheus Tavares. Compartilhar este post Link para o post Compartilhar em outros sites