質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

2546閲覧

PHP:sprintfの仕様について

igaiga

総合スコア144

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2016/06/26 07:50

###前提・実現したいこと
sprintfで例えば10万円から100000の書式に変更したいのですが、想定の数字から1を引いた値が吐き出されます。(正しく吐き出される場合もあります。)
sprintf('%d'の部分がいけないのだろうと思いますが、どのようにすれば正しい数値がとれるのでしょうか?
恐れ入りますが、ご教授いただければ幸いです。

###foreachの中に入れたソースコード

$rentamount = str_replace("万円", "",$url2->rent_amount);//賃料 $rent_array[$j] = sprintf('%d', $rentamount * 10000);

###値は以下のようなイメージです

$rentamount = 8.79 //1回目 $rentamount = 8.98 //2回目 $rentamount = 9.12 //3回目 $rent_array = Array ( [0] => 87899 [1] => 89800 [2] => 91199 )

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

roundを使う方法もありますが,別の方法としては

php

1// 小数点桁数ゼロの小数として表示する 2printf("%.0f\n", 8.79 * 10000);

などがあるでしょう.実質これもround相当かと思います.

投稿2016/06/26 08:37

編集2016/06/26 08:38
mpyw

総合スコア5223

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

igaiga

2016/06/26 09:01

ありがとうございます! printf("%.0f\n", 8.79 * 10000);だと値の末尾に¥nがついてしまうようなので printf("%.0f", 8.79 * 10000);としてみたところ、想定通り動きました。
guest

0

ベストアンサー

これはsprintfの問題ではなく、数値演算の側での問題です。

PHPを含め多くの言語では、小数をIEEE 754という形式で表していますが、この形式では2進法を使う都合上、0.01を正確に表すことができません。そのため、8.79*1000087899.99999999999という値を取ることになり、これをintへ変換する際に切り捨てるため、意図した値から1小さくなってしまいます。

まずround()関数を使って、整数まで丸めておきましょう。

投稿2016/06/26 08:21

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

igaiga

2016/06/26 08:52 編集

ありがとうございます! $rent_array[$j] = sprintf('%d', $rentamount * 10000); を下記に変更したところ、想定通りの値が出るようになりましたが使い方あってますでしょうか? $rent_amount[$j] = round($rentamount * 10000);
guest

0

この現象はsprintfの仕様ではなく、小数を計算する際の誤差の問題です。

PHP

1$rentamount = str_replace("万円", "",$url2->rent_amount);//賃料 2$tmp = $rentamount * 10000; 3var_dump($tmp); 4$rent_array[$j] = sprintf('%d',$tmp );

とすると、1少なくなる数を計算した場合、sprintf()に渡される前に n.999999という感じになっているはずです。

PHPに限らず、プログラム言語での小数計算は精度を指定しないと切り捨て問題が発生する可能性があります。
PHP 小数計算 誤差
PHPの場合、これを厳密に解決するには
BC Math関数
を使用する必要があります。

PHP

1<?php 2 3 4$rentamount[] = 8.79 ; 5$rentamount[] = 8.98 ; 6$rentamount[] = 9.12 ; 7 8 9foreach($rentamount as $key => $val){ 10 $rent_array[] = bcmul($val , 10000,0); 11 12} 13 14var_dump($rent_array); 15/* 16array(3) { 17 [0]=> 18 string(5) "87900" 19 [1]=> 20 string(5) "89800" 21 [2]=> 22 string(5) "91200" 23}*/

が、BC Math関数は標準ではインストールされないので、インストールする必要があります。

CentOSでyumでPHPがインストールされてるなら

bash

1# yum install php-bcmath

という感じです。レンタルサーバ等でインストールされてないならこの方法は諦めるしかありません。

その場合、
今回のケースだと、単純に10万倍したいだけなので文字列として操作しちゃうというのもありかもしれません。

流れとしてはこんな感じでしょうか。

  1. str_replace()で”万円”を削除する
  2. strpos()で小数点の位置を特定する。特定した位置と全体の文字数から、0埋めしないといけない桁数を計算する
  3. str_replaceで小数点を削除する
  4. 2で取得した数の0をsprintf()で0埋めするか、文字列として連結する。

投稿2016/06/26 08:14

編集2016/06/26 08:27
tanat

総合スコア18713

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanat

2016/06/26 08:28

maisumakunさんの回答の通り、round()を使えば解決しますね。
igaiga

2016/06/26 08:53

ありがとうございます! 今のところ、レンタルサーバなのでround()でやってみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問