ソフトウェア開発者の日常

こだわりなく書きたいことを書いていきます。

PHP:小数点以下の切り捨て誤差の対処

JavaScriptの計算誤差への対処を書きました。
ajya.hatenablog.jp

このとき、同時にPHPの小数点以下の切り捨て誤差の対処もしました。

JavaScriptとは異なる箇所で誤差発生

JavaScriptでは、36.3×700=25,410になるはずのところ、25,409になっていました。
PHPでは、同じ値の計算でも36.3×700=25,410になっていました。

この値を小数点以下の切り捨てのためにfloor()関数で値を求めると、25,410が25,409になります。
PHP: floor - Manual

f:id:AJYA:20171218125623j:plain
photo credit: eloyruizmontañez Very Scientific Stuff 2 3000x2250 via photopin (license)

文字列に変換してから切り捨てる

PHPのマニュアルにも、浮動小数点数の精度について記述があります。
PHP: 浮動小数点数 - Manual

マニュアルには、任意精度数学関数のBC Math 関数が紹介されています。
PHP: BC Math 関数 - Manual

BC Math 関数を使えばいいのでしょうが、今回はstrval()関数で文字列に変換してから、切り捨てることにしました。
PHP: strval - Manual

具体的には

$a = 36.3 * 700;
$a = floor(strval($a));

としました。
こうすることで、期待したとおりの値になりました。


JavaScriptに続いてPHPでも計算誤差に気がついたのは初めてです。
誤差が積み重なると、大きな値の違いになるので、気をつけて結果を確認しなければなりません。

自宅にピアノが設置されました

ピアノの購入を決め、ピアノを置く場所を確保するために片づけをしました。
ajya.hatenablog.jp
ajya.hatenablog.jp

そしてピアノが搬入されました。
f:id:AJYA:20171217130225p:plain

ピアノ搬入は2人がかかり

ピアノの搬入は10時45分くらいから行われました。
事前に聞いていましたが、軽くても200㎏くらいの重さがあるというのに、2人で持ち上げるのは驚きです。
ピアノの搬入 - ヤマハ – 日本

玄関からリビングに入り、向きを変えてダイニングの一角にピアノは搬入され、設置されました。
楽器店の方もみえていて、設置が終わったピアノを弾いてもいいよと言っくれても、こどもは恥ずかしいのか全然弾こうとしません。

楽器店の方が帰られてから、やっと子どもはピアノを弾き始めました。
不思議と両手を使っています。
弾くといっても、習ったわけではないので、適当に鍵盤を押さえているだけです。
それでも、なんだかちゃんと弾いているように聞こえるのは、ピアノの響きがいいんでしょうね。


自宅にピアノがある生活は全く予想していませんでした。
ピアノ教室の見学は来年の予定です。
長く続けてくれるとうれしいです。

1週間の振り返り(2017/12/9〜2017/12/15)

会社にいただいた梅干しをお昼ご飯にいただきました。
f:id:AJYA:20171216142424p:plain
全然酸っぱくなく美味しかったです。

  • 2017/12/9(土)
    保育園でクリスマス音楽会が行われたので行きました。
    子ども自身もそうですが、みんな一生懸命に頑張って歌ったり演じたりしていました。

ajya.hatenablog.jp

  • 2017/12/10(日)
    母の誕生日が近いので、ショートケーキを子どもと持って行きました。
    車の中で、おばあちゃんに言うことの練習をしてバッチリだと思っていたら、なぜか逆のことを言っていました。
    本番に弱いタイプかもしれません。
    ケーキを持って行ったあとは、ピアノを置けるように模様替えをしていいました。

ajya.hatenablog.jp

  • 2017/12/11(月)
    お客さんから計算が1合わないという連絡がありました。調べてみると、JavaScriptでの計算による誤差が発生していました。
    修正しましたが、6年近く稼働しているシステムで、これまで気づかれていないのは、偶然なのか気がついていないだけなのか、わかりません。

ajya.hatenablog.jp

  • 2017/12/12(火)
    行きはJR東海は止まっていて、帰りは運転再開していましたが、振替乗車票が配られていたので、名鉄に乗りました。
    当然混雑しているので、会社に着く前からぐったりしたくなるほど疲れました。

ajya.hatenablog.jp

  • 2017/12/13(水)
    システム作成の依頼をされた際の情報で、これは本当に正しいのかという内容がありました。
    これは正しいですかと質問して正しかった際に気分を害される可能性があったので、お客さんに必要な情報をくださいとお願いしました。
    なんどかやり取りする中でもお客さんは必要な情報を連絡しますと返事をされるばかりだったので、正しかったのかと思い始めた頃に、これはなぜこうなっているのかとお客さんと同じ支社の別の方から電話ありました。
    システム作成の依頼をされた際の情報のとおりで話を進めているので、システム作成の依頼をされた際の情報が間違っているんですねと話して終わりました。
    依頼をする際は、情報を正しく送ってほしいです。
  • 2017/12/14(木)
    お客さんから見積について連絡がり、お客さんが想定していた金額も知らされました。
    随分予算と違う結果になっていますが、お客さんが依頼元から情報をあまり引き出さず金額を決めたためです。
    機能を削ってもらって、費用を抑える以外予算に近づける方法はありません。
  • 2017/12/15(金)
    他の部署に依頼してあったシステムの動作確認を行うと、想定と異なる結果になりました。
    なぜこのような動作をするのかとソースコードを確認したら、難しく作りこんでいます。
    お客さんからの要望をそのまま受け入れると確かに作りこんだ内容になりますが、実現する方法はもっと簡単にあります。
    もっと簡単にする方法のアイデアと合わせて、他の部署に修正の依頼をしました。


1日に見積を6枚も作成する日もあったりで、毎日忙しいです。
そんな中で、予算と金額が合わないという連絡があり、なんとかならないかと言われても、予算内で作成すると言ってくれる会社を探して依頼すればいいのではないかと思ってしまいます。
連絡がある会社とは、いろいろあって印象が悪いので、無理をして値下げをして対応しようという気にはなりません。

振替乗車票はなくせないのか

12月12日に発生したJR東海東海道本線でのパンタグラフ及び電力設備の損傷による運休に巻き込まれました。
http://jr-central.co.jp/news/release/_pdf/000035909.pdf

当日の朝、会社に行くために駅に着くと長蛇の列で、何事が起きたのかと思いました。
列の先頭を見ると、JR東海の改札の前で駅員さんが振替乗車票を配っています。

長蛇の列の最後尾がどこかもよくわかりません。
列に並んだら、何分後に振替乗車票をもらえるのかもわかりません。
振替乗車票をもらうのを諦め、さっさと名鉄の改札へ行き自費で改札を通り、会社に向かいました。

会社に着く直前にYahoo!乗り換え案内アプリの運行情報を見て、状況をやっと把握しました。
f:id:AJYA:20171215123534p:plain

帰りは運転再開していましたが、大幅に運行本数が減らされていました。
運転再開後も、JR東海の改札近くの通路で駅員さんが振替乗車票を配っていました。
幸いすぐに振替乗車票はもらえる状態だったので、振替乗車票をもらって名鉄に乗りました。

定期券のICカードを使えば、振替乗車票はなくせないのか?

今回振替乗車票を片道だけもらいました。
そのためにJR東海から名鉄まで移動しなければなりません。
また、片道は振替乗車票をもらわず自費です。

振替乗車票を駅員さんが手渡しするのもあって列が長くなると思います。
振替乗車票を配るのを止めて、定期券のICカードであれば区間がわかるので、鉄道会社の垣根を超えて相互にやり取りして、改札を通過できるようにできないのでしょうか。
定期券のICカードもそれなりに普及しているはずなので、振替乗車票をもらうための長蛇の列も短くなるのではないかと思います。
定期券ではないICカードを使われている方や、切符を購入された方には、解決策になっていませんが、少しでもよりよくなる方向だと考えるので、検討して欲しいです。


会社に着く直前にYahoo!乗り換え案内アプリの運行情報を見て、なぜ通知されなかったのかと考えたら、ディズニーランドへ遊びに行く際に、Gmailアプリと一緒に、Yahoo!乗り換え案内アプリも通知されないように設定を変更したことを思い出しました。
ajya.hatenablog.jp
なにを変更したのか控えず、設定を戻さなかったため、今回の運行情報に気づきませんでした。

4歳8か月になりました

子どもが生まれて4年と8ヶ月です。気づいたことや出来事を書いていきます。

f:id:AJYA:20171213235009j:plain
photo credit: Photosightfaces Happy kids via photopin (license)

  • 写真を撮ることに興味があるようです。
    変顔をして撮らせて、それを見て、自分にも撮らせてと言います。
    落として壊されてはたまらないので、まだ撮らせてはいません。
    以前は写真を撮るときは硬直しているだけだったのが、ポーズを決めてくれるようになったのはありがたいです。
  • 保育園でお手紙渡すのが流行っているそうです。
    お手紙を渡そうとすると他の子が取ったりすることもあって、持たせないようにしています。
  • 寝る前に何度もお休みと言うときがあります。
    言われるたびに返しています。
    暗くなるまでずっと繰り返すこともあります。
  • クリスマスケーキを作りたいと言いました。
    買うつもりでいましたが、方針変更です。
    妻が大丈夫そうな作り方を調べました。
    それでも作る日は大騒ぎになりそうです。
  • インフルエンザの予防接種2回目を受けました。
    1回目と同様に、泣かずに予防接種を受けたそうです。
  • 髪の毛を自分で結ぼうとします。
    まだできなくて癇癪を起こすので、練習しないとすぐにはできないよとなだめています。
  • ピアノを購入しました。
    1月にピアノ教室を見学して、2月位から習わせるつもりでいます。
    長く続けて欲しいです。

ajya.hatenablog.jp
ajya.hatenablog.jp

  • クリスマスツリーを出しました。
    雪に見立てた綿をちぎって細かく飾りつけました。
    細かすぎて取れるので、取れた分は他の綿と一緒にしていっています。
  • 自転車に乗る練習を久しぶりにしました。
    脚力がついたのか、直線ではスムーズですが、広い駐車場でもぶつからないようにハンドルを切りすぎて抵抗が増えて、なかなか走れないです。
  • お手伝いをいろいろしてくれます。
    ごみを集めたり、洗濯物をたたんだり、ショッピングカートを押したり、卵をかきまぜたりといろいろやりたがります。
  • 自宅と保育園ではずいぶん様子が違うようです。
    保育園では、おしとやか、と言われる程度におとなしくしているようです。
    自宅では暴れまわっています。
  • ジャムの瓶に吸い付いて、内出血しました。
    一人で遊んでいるうちにやったそうです。
    唇の下が内出血して、周りの人みんなに、どうしたのと聞かれました。
  • 神経衰弱が得意です。
    カードの傷を覚えているというのもありますが、よく覚えています。
    こちらが真剣に覚えようとしても負けてしまいます。
  • また風邪を引きました。
    鼻の症状から発症するので、耳鼻咽喉科に通っています。
    なかなか治らないので、妻と僕が受診したことがある耳鼻咽喉科を子どもに受診させました。
    これまで子どもが受けたことがない、鼻の中を吸い取る治療をしたら、驚くほど症状がよくなりました。
    症状からするとこれまで処方された薬は間違っていないということでした。
    症状の改善具合から、これまでの耳鼻咽喉科は受診しないと判断しています。

ajya.hatenablog.jp

  • クリスマス音楽会が行われました。
    あかずきんちゃん役でした。
    風邪が完全に治っていなくて、前日に頭が痛いと言い出して休んで、保育園から連絡があったりもして、当日大丈夫かと心配もしましたが、無事参加できました。

ajya.hatenablog.jp

  • 抹茶のケーキを食べます。
    少しだけもらいましたが、大人でも苦手な人がいそうな濃い味をよく食べているなと感心しました。


耳鼻咽喉科医院を代えて子どもの症状がずいぶんよくなりました。
もっと早く連れて行けば、早く治って薬を飲ませなくて済んだかもしれないと思ってしまいます。

2017年に買ってよかったものはビデオカメラです

今週のお題今年買ってよかったもの」で、悩んだ末に購入したビデオカメラが今年買ってよかったものです。
ajya.hatenablog.jp


保育園の行事や旅行での撮影で活躍しています。
入園式に参加しました - ソフトウェア開発者の日常
夕涼み会に行ってきました - ソフトウェア開発者の日常
運動会に行ってきました - ソフトウェア開発者の日常
二泊三日家族旅行:二日目(11月2日(木)) 東京ディズニーランドで一日中遊ぶ - ソフトウェア開発者の日常


保育参観のときは、撮影できるとは思わずに持っていかなかったのが残念です。
保育参観に行ってきました - ソフトウェア開発者の日常


保育園の講堂の舞台で行われる行事では、舞台だけ照明で明るくなり周りは暗くなりますが、しっかり撮れています。
七夕発表会に行ってきました - ソフトウェア開発者の日常
クリスマス音楽会に行ってきました - ソフトウェア開発者の日常


屋外で手持ちの撮影時は、手振れ補正がしっかり効果を発揮して、見ていて気持ち悪くなるほど映像が揺れることもありません。
中津川市ふれあい牧場に行ってきました - ソフトウェア開発者の日常


購入するまでどこのメーカーがいいのか、どの機種がいいのかと迷いましたが、満足しています。
どのビデオカメラを買うか悩んでいます - ソフトウェア開発者の日常
続:どのビデオカメラを買うか悩んでいます - ソフトウェア開発者の日常


このビデオカメラで、子どもの成長をいっぱい記録していきます。



JavaScript:計算誤差の対処

JavaScriptで計算している部分で、想定と異なる結果になる場合がありました。
具体的には、36.3×700=25,410になるはずですが、25,409になります。

ブラウザのデバッガで値を確認しても、36.3と700のまま掛け算をしていますが、25,409になります。
検索すると、JavaScriptIEEE 754という規格に従って実装されているためのようです。
IEEE 754 - Wikipedia

f:id:AJYA:20171212124055j:plain
photo credit: Canadian Pacific Do Your Math! via photopin (license)

整数同士なら誤差がでない

対処方法としては、公開されているJavaScriptライブラリを導入する方法もあるようです。
今回計算しているのは1箇所だけだったので、以下の記事を参考に実装しました。
qiita.com
小数点の以下の桁数を把握して、文字列に変換して整数化、整数同士で計算後、小数点以下の桁数を戻すということをしています。

こちらの記事をほぼそのまま利用できますが、2点変更しました。
1点目は、getDotPosition()の

    // 小数点が存在するか確認
   if(strVal.lastIndexOf('.') === -1){

の部分が、小数点が存在しない場合にしか処理しないようになっていて、コメントと合っていません。
lastIndexOf()メソッドは、検索する文字列が見つからない場合は、-1を戻すためです。
developer.mozilla.org>
コメントのとおりに動作するように、

    // 小数点が存在するか確認
   if(strVal.lastIndexOf('.') !== -1){

に変更しました。

2点目は、calcSubtract()の

    // 10^N の値を計算
    var power = Math.pow(10,max);

    // 整数値で引き算した後に10^Nで割る
    return (intValue1-intValue2) / power;

の部分が引き算の例だったので、掛け算用に

    // 10^N の値を計算
    if (max == 1) {
        max = max + 1;
    } else {
        max = max * max;
    }
    var power = Math.pow(10,max);

    // 整数値で掛け算した後に10^Nで割る
    return (intValue1*intValue2) / power;

に変更しました。
maxが1の場合は2、それ以外はmax同士を掛けています。
小数点以下の位が多いほうに合わせて両方の値に同じだけ掛けているので、整数値で計算します。
計算後、掛けた分で割らなければいけないので、maxを操作しています。


JavaScriptで計算誤差に気がついたのは初めてです。
小数点以下を伴う計算であればいつでも起きる可能性があるので、気にしておかなければならない点です。