パスワードを忘れた? アカウント作成
13749899 journal
変なモノ

nemui4の日記: 月を入力すると日数が出るようにするには 26

日記 by nemui4

上司のおっさんに「月を入力すると日数が出るようにするにはどうすれば?」と聞かれたのでコレを教えてあげた心温まる話
https://togetter.com/li/1279312
パット見まるでわからない・・・(数学疎いな)
こんなの全然知らなかったのは自分だけ?

in my case.
月と日数の配列(table)作って、2月だけ閏年判定関数どっかから拾ってくるか、利用する範囲で対応できる配列作っるかしちゃいそう。

この議論は、nemui4 (20313)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
  • by hahahash (41409) on 2018年10月22日 10時16分 (#3501989) 日記

    例えば、1月と2月だけでよければ、
    31 = a * 1 + b
    28 = a * 2 + b
    を満たすaとbは(a = -3 b = 34)なので、
    days(m) = -3 * m + 34

    1~3月までだったら、
    31 = a + b + c
    28 = a * 4 + b * 2 + c
    31 = a * 9 + b * 3 + c
    を満たすのは(a = 3 b = -12 c = 40)になって、
    days(m) = 3 * m**2 - 12 * m + 40

    1~4月なら
    31 = a + b + c + d
    28 = a * 8 + b * 4 + c * 2 + d
    31 = a * 27 + b * 9 + c * 3 + d
    30 = a * 64 + b * 16 + c * 4 + d
    を満たす(以下略)

    • by taka2 (14791) on 2018年10月22日 11時00分 (#3502012) ホームページ 日記

      (x-2)(x-3)(x-4)…(x-12)は、xが1の時のみ非0で、2~12の時は0になる。x=1の時は-39916800なので、
      f1(x)=(x-2)(x-3)(x-4)…(x-12)*31/-39916800
      とすれば、f1(1)=31で、f1(2)~f2(12)=0になる。
      同様に、
      (x-1)(x-3)(x-4)…(x-12)は、xが2の時のみ非0で、1および3~12の時は0になる。x=2の時は3628800なので、
      f2(x)=(x-1)(x-3)(x-4)…(x-12)*28/3628800
      とすれば、f2(2)=28で、f2(1)、f2(3)~f2(12)=0になる。

      同じようにして f3(x)~f12(x)を求めて、
      f(x)=f1(x)+f2(x)+…+f12(x)
      とすれば、この関数f(x)は、f(1)=31, f(2)=28, …を満たす。

      展開は面倒そうですが、方程式を解かなくても定式化できます。

      親コメント
    • by nemui4 (20313) on 2018年10月22日 11時08分 (#3502016) 日記

      なるほど、解が先にあってそこから数式を導き出す(近似する)んですね。

      togetterの式をExcelに打ち込んでみたら2月が27日で4月が29日になった。
      数字を打ち込み間違えたかな。

      =INT(
      -11/907200*A2^11
      +163/181440*A2^10
      -37/1260*A2^9
      +13481/24192*A2^8
      -2055371/302400*A2^7
      +240683/4320*A2^6
      -28268521/90720*A2^5
      +85774775/72576*A2^4
      -446998571/151200*A2^3
      +46351537/10080*A2^2
      -221017/56*A2
      +1416
      )

      セル"A2"に月の数字を入れています。

      親コメント
      • by ktmizugaki (46208) on 2018年10月22日 16時49分 (#3502284) 日記

        切り捨ててるせい。小数で計算する関係で誤差が出ており、例えば 2月は 27.9999999999991 になっている。

        --
        svn-init() {
          svnadmin create .svnrepo
          svn checkout file://$PWD/.svnrepo .
        }
        親コメント
        • by nemui4 (20313) on 2018年10月23日 7時38分 (#3502636) 日記

          ありゃ、素でやると四捨五入では丸めてないのか・・・

          昔いた事務所の経理の人が、Excelで集計すると誤ってる時があるので必ずデカイ電卓で検算するって言ってたっけ。

          親コメント
          • by ktmizugaki (46208) on 2018年10月23日 14時10分 (#3502840) 日記

            いや、素じゃなくてINT関数で切り捨ててますよ……。

            --
            svn-init() {
              svnadmin create .svnrepo
              svn checkout file://$PWD/.svnrepo .
            }
            親コメント
          • by PEEK (27419) on 2018年10月23日 14時18分 (#3502850) 日記

            EXCELで四捨五入はROUND関数ですね。
            INT関数は指定した数値を超えない最大の整数を返すってやつ。
            なので単純な切り捨てでもない。
            INT(1.5)→1
            ROUNDDOWN(1.5,0)→1
            INT(-1.5)→-2
            ROUNDDOWN(-1.5,0)→-1

            --
            らじゃったのだ
            親コメント
            • by nemui4 (20313) on 2018年10月23日 16時15分 (#3502943) 日記

              てっきりINTが四捨五入でまるめてくれるんだと思ってました。

              >EXCELで四捨五入はROUND関数ですね。
              >INT関数は指定した数値を超えない最大の整数を返すってやつ。

              Excel初心者(じぶん)が躓く罠っぽい(単なる早とちりか)

              親コメント
  • by minet (45149) on 2018年10月22日 10時39分 (#3502002) 日記

    11次近似!
    こりゃ一本取られたね。
    1〜12までの整数に対して整数値が返さればいいので、11次曲線で完全に計算できますね!
    月ごとの日数をテーブルに持つ必要がなくてストレージにも優しいですね(^^)

    • by nemui4 (20313) on 2018年10月22日 10時48分 (#3502007) 日記

      >11次近似!

      そんなワードが出てくると脳の血流が停滞します。
      2次3次くらいならなんだかわかるけど11次まで跳ね上がると?ってなってしまう非数学脳。
      #理系のはしっこにいるつもりなのに数字(学)には弱い・・・

      親コメント
  • by minet (45149) on 2018年10月22日 12時11分 (#3502066) 日記

    以下の条件でやってみる。

    • Excelの数式で計算、マクロは禁止
    • 月(1~12の整数)から日数を得る
    • 閏年は考慮しない(年を得られないので)
    • 日付時刻系の関数は禁止
    • 月以外のセルの参照は禁止

    ついでに、数式をなるべく短くすることを考える。
    (以下では、月はA1セルに格納されているものとする。)

    まず、愚直にテーブル引きで実装して、

    =INDEX(A1,31,28,31,30,31,30,31,31,30,31,30,31)

    月の値はいずれも30日に近いから、30から差分を増減させるように書き換えると、

    =30+INDEX(A1,1,-2,1,0,1,0,1,1,0,1,0,1)

    これって2月(28日)を別にすると、大の月(31日)と小の月(30日)がほぼ交互に並んでいるように見えて、7月と8月の間だけ順番が飛んでいるように見える。
    ということは、月の値に適当な値を掛けてやって、ちょっとだけ早く進んで7月と8月の間で順番が飛ぶようにしてやれば、奇数判定で大の月が得られる。
    1/7≒0.143なので、月*1.14がよさそうだ。
    つまり、

    =30+ISODD(A1*1.14)+2月の補正 ※擬似コード

    Excel数式では値の比較の結果はFALSE0TRUE1と変換されることを利用すると、2月は(30-2)日と表せるから、
    2月の補正を入れた最終形は、

    =30+ISODD(A1*1.14)-(A1=2)*2

    となった。
    私の頭ではこのあたりが限界のようだ。

    • by nnnhhh (47970) on 2018年10月22日 13時23分 (#3502095) 日記

      =VALUE(DATE(2018,A1 + 1,1) - DATE(2018, A1,1))
      私がぱっと思いついたのはこんなのでした

      親コメント
      • by nemui4 (20313) on 2018年10月22日 14時18分 (#3502126) 日記

        なるほど、次の月の1日(ついたち)から一日引くんですね。
        Excel用だと簡単かつ完璧そう。

        #Excelあんまり使ってないので関数も殆ど知らない・・・

        親コメント
      • by minet (45149) on 2018年10月22日 15時15分 (#3502174) 日記

        日付関数ありで、翌月いっぴ-1日の日付で出すなら、
        =DAY(DATE(1,A1+1,1)-1)
        こんな感じですかね。
        Excelが13月を翌年1月とみなす挙動と、「1」を2桁表記の1901年とみなす挙動を利用しているのでトリッキーですが、
        A1を年、A2を月とした場合は
        =DAY(DATE(A1,A2+1,1)-1)
        となるので、まぁまぁ可読性はあるかと。

        親コメント
        • by nnnhhh (47970) on 2018年10月22日 15時48分 (#3502202) 日記

          おー確かに私がやったように元月の1日を引くコタ無いですね
          -1の日付で行けますね

          親コメント
        • by PEEK (27419) on 2018年10月23日 14時52分 (#3502868) 日記

          =DAY(((A1+1)&"/1")-1)
          とすると年をその時点での年で計算するのでその年がうるう年かどうかで2月の最終日付が変わるようになる。

          --
          らじゃったのだ
          親コメント
          • by minet (45149) on 2018年10月23日 18時38分 (#3503038) 日記

            お、こりゃナイス。
            ロケールに依存しそうですが、日本内限定なら大丈夫かな。

            # でもね、日本でも
            # ある日客先から「エクセル(のシートとCSVを使う作業が含まれるソリューション)がおかしくなった!」って呼び出されて、調査したら
            # なぜか一台のWindowsで地域設定がオランダに変わっていたとさ

            親コメント
    • by TarZ (28055) on 2018年10月22日 15時04分 (#3502163) 日記

       これ短くていいですね。

       私がExcelでやると愚直にテーブル使ってこんな感じ↓です(A1セルに月が入っている前提)。ちょっと長いですね。

      =MOD(QUOTIENT(62648012,(4^A1)),4)+28

       Cで書くと意図が明瞭になるのに、Excel関数だとすごくわかりづらい…。

      親コメント
    • by nemui4 (20313) on 2018年10月22日 13時23分 (#3502094) 日記

      すげー、そうなっちゃうんだ。

      わたしの in my case だと、極単純に月と日
      #m,d
      1,31
      2,28
      3,31
      4,30
      ...
      のテーブルをワークシートの何処かに作っておいて vlookupで引っ掛けようと思ってました。
      #これだと無駄が多い

      親コメント
typodupeerror

犯人は巨人ファンでA型で眼鏡をかけている -- あるハッカー

読み込み中...